SimGrid 3.7.1
Scalable simulation of distributed systems
|
Our program is well and good, but if we had to write a longer program, explicitely waiting for messages of a given type would not be really practical. To add some more dynamism, what we want to do is to attach callbacks to the several messages types, and tell GRAS that we are ready to deal with new messages. That's what we will do now.
First of all, we define the callback we want to attach to the arrival of the "hello" message on the server. Its signature is fixed: it accepts two arguments of relative types gras_msg_cb_ctx_t ctx
and void
. The first one is a working context we should pass to GRAS when speaking about the message we are handling while the second is the payload. The callback returns an integer being its error code, just like the "main()" function. Here is the actual code of our callback:
int server_hello_cb(gras_msg_cb_ctx_t ctx, void *payload) { gras_socket_t client = gras_msg_cb_ctx_from(ctx); fprintf(stderr, "Cool, we received the message from %s:%d.\n", gras_socket_peer_name(client), gras_socket_peer_port(client)); return 0; } /* end_of_callback */
Then, we have to change the server code to use this callback instead of gras_msg_wait. This simply done by a construct like the following:
gras_cb_register("hello", &server_hello_cb);
Once the callback is declared and attached, the server simply has to call gras_msg_handle to tell GRAS it's ready to handle for incoming messages. The only argument is the maximum delay we are disposed to wait for a message. If the delay is negative, the process will block until a message arrives. With delay=0, the process just polls for already arrived messages, but do not wait at all if none arrived yet. If the delay is greater than 0, the process will wait for at most that amount of seconds. If a message arrives in the meanwhile, it won't even wait that long.
Sometimes, you want to handle all messages arriving in a given period without really knowing how much messages will come (this is often the case during the initialization phase of an algorithm). In that case, use gras_msg_handleall . It has the same prototype than gras_msg_handle, but waits exactly the passed delay, dealing with all the messages arriving in the meanwhile.
We have no such needs in our example, so the code simply reads:
gras_msg_handle(60);
The whole program now reads:
/* Copyright (c) 2006, 2007, 2010. The SimGrid Team. * All rights reserved. */ /* This program is free software; you can redistribute it and/or modify it * under the terms of the license (GNU LGPL) which comes with this package. */ #include <stdio.h> #include <gras.h> int server_hello_cb(gras_msg_cb_ctx_t ctx, void *payload) { gras_socket_t client = gras_msg_cb_ctx_from(ctx); fprintf(stderr, "Cool, we received the message from %s:%d.\n", gras_socket_peer_name(client), gras_socket_peer_port(client)); return 0; } /* end_of_callback */ int server(int argc, char *argv[]) { gras_socket_t mysock; /* socket on which I listen */ gras_init(&argc, argv); gras_msgtype_declare("hello", NULL); mysock = gras_socket_server(atoi(argv[1])); gras_cb_register("hello", &server_hello_cb); gras_msg_handle(60); gras_exit(); return 0; } int client(int argc, char *argv[]) { gras_socket_t mysock; /* socket on which I listen */ gras_socket_t toserver; /* socket used to write to the server */ gras_init(&argc, argv); gras_msgtype_declare("hello", NULL); mysock = gras_socket_server_range(1024, 10000, 0, 0); fprintf(stderr, "Client ready; listening on %d\n", gras_socket_my_port(mysock)); gras_os_sleep(1.5); /* sleep 1 second and half */ toserver = gras_socket_client(argv[1], atoi(argv[2])); gras_msg_send(toserver, "hello", NULL); fprintf(stderr, "That's it, we sent the data to the server on %s\n", gras_socket_peer_name(toserver)); gras_exit(); return 0; }
And here is the output (unchanged wrt previous version):
$ ./test_server 23451 & ./test_client 127.0.0.1 23451 Client ready; listening on 1024 That's it, we sent the data to the server on 127.0.0.1 [arthur:client:(27507) 0.000019] [gras/INFO] Exiting GRAS Cool, we received the message from 127.0.0.1:1024. [arthur:server:(27505) 0.000013] [gras/INFO] Exiting GRAS $ $ ./test_simulator platform.xml test.xml Client ready; listening on 1024 That's it, we sent the data to the server on Jacquelin [Boivin:client:(2) 0.000000] [gras/INFO] Exiting GRAS Cool, we received the message from Boivin:1024. [Jacquelin:server:(1) 0.000000] [gras/INFO] Exiting GRAS $
Our little example turns slowly to a quite advanced GRAS program. It entails most of the mecanism most program will use.
There is one last thing you should know about callbacks: you can stack them, ie attach several callbacks to the same message. GRAS will pass it to the lastly attached first, and if the returned error code is not 0, it will pass it also to the next one, and so on. I'm not sure there is any sensible use of this feature, but it's possible ;)
Back to the main Simgrid Documentation page |
The version of SimGrid documented here is v3.7.1. Documentation of other versions can be found in their respective archive files (directory doc/html). |
Generated by ![]() |