![]() |
Maestro Types |
void read(int&); // read an integer from the message void read(void *buf, int size); // read a buffer from the message void write(int); // write an integer into the message void write(void *buf, int size); // write a buffer into the message unsigned size(); // get total size of the message unsigned getPos(); // get current position of message pointer void setPos(unsigned offset); // set position of message pointer void seek(int offset, Maestro_MsgSeek whence); // seek to the specified offset. // Pack an array of messages into the given msg. void pack(Maestro_Message *msgs, unsigned nmsgs); // Unpack an array of messages from the given msg. void unpack(Maestro_Message *&msgs, unsigned &nmsgs); void reset(); // reset the message int isWritable(); // return non-zero iff the message is writableRead/write operations on Maestro messages follow the stack paradigm (first in/last out). This is convenient in the layering architecture of Maestro/Ensemble, where layers push headers on outgoing messages and pop matching headers from incoming messages. There are also stream-like message I/O operators defined for basic types, such as int, Maestro_EndpID, Maestro_EndpList, Maestro_String. For example, consider the following code at the sender side:
Maestro_Message msg; Maestro_EndpID endp; Maestro_EndpList elist; Maestro_String s("hello world"); ....... msg << endp << elist << s; // push endp, elist, s into msg memb.cast(msg); // multicast msg to the memb's groupThis could correspond to something like this at the destination:
receivedMsg >> s >> elist >> endp; // pop ent, elist, s from the msg
Maestro_Message m1, m2, m3; int i, pos; m1 << 5; // push an integer into m1 pos = m1.getPos(); // remember the current offset at m1 m1 >> i; // pop an integer from m1 m1.setPos(pos); // rewind m1 (which becomes read-only) m2 = m1; // make m2 an alias of m1 (m2 is read-only) m3 <<= m1; // copy m1 into m3 (m3 is writable)
NOTE: Byte ordering issues are not yet addressed in Maestro messages.
Maestro_EndpID endp; Maestro_Message msg1, msg2; ..... msg1 >> endp; // pop endp from the message msg2 << endp; // push endp onto the message cout << endp; // print out the value of endp
struct Maestro_ThreadOps { int stackSize; }; static void create(void (*proc)(void*), void *arg, Maestro_ThreadOps *ops = 0, Maestro_ErrorHandler *error_handler = 0);A call to Maestro_Thread::create(proc, arg) invokes proc(arg) in a separate thread. The size of the thread's stack can be adjusted with the ops argument.
Maestro_Semaphore sema; sema.dec();
Maestro_Lock lck; lck.lock(); // acquire the lock ....... lck.unlock(); // release the lock
The public methods defined by Maestro_Barrier are open(), close(), pass(), isOpen(), and isClosed().
Example:
Maestro_Barrier hb; hb.pass(); // doesn't block since the barrier is open hb.close(); // closes the barrier hb.pass(); // blocks until another thread calls open()
void panic(char *context); void panic(hot_err_t err, char *context);In the default implementation of panic() methods in the Maestro_ErrorHandler class, when panic() is invoked, an error message is printed, after which the process is terminated.
In order to be readable/writable from/to a Maestro_Message object, a subclass of Maestro_Base must overload the following two operators:
virtual void operator << (Maestro_Message& msg); // reading itself from msg virtual void operator >> (Maestro_Message& msg); // pushing itself onto msgThat is, a subclass of Maestro_Base is required to "know" how to read/write itself from/into a message if it is to support stream-like message I/O operations.
Maestro_String s1; // create an empty string Maestro_String s2("hello world"); cout << s2 << endl; // print "hello world" s1 = s2; assert(s1 == s2); Maestro_String s3; // s3 is empty Maestro_Message m; m << s1; m >> s3; assert(s1 == s3);
Maestro_OrderedSet implements standard operations on ordered sets: union, intersection, difference, and random access. As a subclass of Maestro_Base, Maestro_OrderedSet supports stream-like standard output and message I/O.
struct Foo { Foo(Foo& f) { key = f.key; value = f.value; } int operator==(Foo& f) { return (key == f.key); } int key, value; }; // Note the syntax here! Parentheses () are used // where the angle brackets <> would be used in a // template instantiation: typedef Maestro_OrderedSet(Foo) FooList; FooList L; // creates an empty list assert(L.size() == 0); Foo f; f.key = 1; f.value = 2; L += f; // add f to L assert(L.size() == 1); Foo f2; f2.key = 1; // Note that f == f2 f2.value = 3; FooList L2(f2); // L2 contains one element, f2 assert(L2.size() == 1); assert(L2.contains(f2)); assert(L2[f2] == 0); // index of f2 in L2 is 0 assert(L2[0] == f2); // f2 is the 0'th element in L2 FooList L3(L2); // L2 and L3 have now the same contents L3.clear(); // remove all elements from L3 assert(L3.size() == 0); assert(f == f2); // Note that L already contains f L += f2; // f2 is *not* added to L since f == f2 assert(L.size() == 1); Foo f3; f3.key = 5; f3.value = 4; L += f3; // add f3 to L assert(L.size() == 2); L -= f; // remove f from L assert(L.size() == 1); L -= f; // can't remove same thing twice assert(L.size() == 1); L3 = L; // now L and L3 have the same contents L += L2; // L = set union of L and L2 L -= L2; // L = set difference of L and L2 L &= L2; // L = set intersection of L and L2 FooList L4; L4 <<= L; // L4 "steals" the contents of L assert(L.size() == 0); // L has become empty!There are several ordered-set types defined in Maestro, such as Maestro_EndpList and Maestro_MessageList. Maestro_EndpList defines operators for message I/O and standard output, for example:
Maestro_Message msg; Maestro_EndpID e1, e2, e3; Maestro_EndpList L, L2; L += e1; L += e2; L += e3; cout << L; // print the contents of L msg << L; // push L into the message msg >> L2; // read the list into L2