/* * The Unix Channel * * by Michel Beaudouin-Lafon * * Copyright 1990-1993 * Laboratoire de Recherche en Informatique (LRI) * * Client side: services * * $Id$ * $CurLog$ */ #include "Service.h" /*?class UchService An object of class \typ{UchService} (derived from \typ{UchMsgStream}) exists in a client process to represent the server it is connected to. The class \typ{UchService} is virtual: you must create subclasses that redefine at least \fun{NewMessage} from class \fun{UchMsgStream}, and if necessary \fun{ConvertAnswer}. \fun{NewMessage} should decipher the incoming message, transform it into an event, and put in into the event queue with \fun{PutEvent}. It can also handle non event messages (for instance errors). ?*/ /*?class UchMsgQueue An event queue is a linked list of events. Events are normally appended to the end of the queue and extracted from the beginning. ?*/ /*?nodoc?*/ UchMsgQueue :: UchMsgQueue () : CcuSmartData (), Queue () { } /*?nodoc?*/ UchMsgQueue :: ~UchMsgQueue () { } #ifdef DOC /*? Append an event to the queue. ?*/ void UchMsgQueue :: Put (UchMessage* msg) { } /*? Put an event back in the queue (therefore it becomes the first event of the queue). ?*/ void UchMsgQueue :: PutBack (UchMessage* msg) { } /*? Return the first event from the queue and remove it. ?*/ UchMessage* UchMsgQueue :: Get () { } /*? Return the first event from the queue without removing it. ?*/ UchMessage* UchMsgQueue :: Peek () { } #endif /* DOC */ /*? Construct an empty service. ?*/ UchService :: UchService () : UchMsgStream (), EvQueue (0) { } /*? Construct a service connected to address \var{a}. ?*/ UchService :: UchService (UchAddress* a) : UchMsgStream (0, a), EvQueue (0) { } /*?nodoc?*/ UchService :: UchService (const UchService& s) : UchMsgStream (s), EvQueue (s.EvQueue) { } /*?nodoc?*/ UchService :: ~UchService () { EvQueue = 0; // deletes it } /*?nodoc?*/ UchChannel* UchService :: Copy () const { return new UchService (*this); } /*? Set the event queue to be used to store the incoming events. If not set, a default event queue is created. This function is intended to share a queue between several servers. ?*/ void UchService :: SetEvQueue (UchMsgQueue* evq) { EvQueue = evq; } /*?nextdoc?*/ UchMessage* UchService :: PeekEvent (bool wait) { Flush (); if (!EvQueue) EvQueue = new UchMsgQueue; UchMessage* ev = EvQueue->Peek (); if (ev || ! wait) return ev; while (! ev) { HandleRead (); ev = EvQueue->Peek (); } return ev; } /*? These functions flush the output buffer, and check the events already in the queue. If there is at least one, it is returned; \fun{GetEvent} also removes it from the event queue. If the event queue is empty and \var{wait} is true, the function blocks until an event arrives, else it returns 0 without blocking. These functions also create the event queue if it was not set with \fun{SetEvQueue}. ?*/ UchMessage* UchService :: GetEvent (bool wait) { Flush (); if (!EvQueue) EvQueue = new UchMsgQueue; UchMessage* ev = EvQueue->Get (); if (ev || ! wait) return ev; while (! ev) { HandleRead (); ev = EvQueue->Get (); } return ev; } /*?nextdoc?*/ void UchService :: PutEvent (UchMessage* ev) { if (! EvQueue) EvQueue = new UchMsgQueue; EvQueue->Put (ev); } /*? These functions are similar to the functions \fun{Put} and \fun{PutBack} on the event queue of the server. They create the event queue if it was not set with \fun{SetEvQueue}, and set the event's server. ?*/ void UchService :: PutBackEvent (UchMessage* ev) { if (! EvQueue) EvQueue = new UchMsgQueue; EvQueue->PutBack (ev); } /*?class UchEventMsg \typ{UchEventMsg} is the base class for event messages to be used with \typ{UchService}s. The difference between an \typ{UchEventMsg} and a \typ{UchMessage} lies in the function \fun{Activate}: event messages add themselves to the event queue. ?*/ /*?nodoc?*/ UchEventMsg :: UchEventMsg () { } /*?nodoc?*/ UchEventMsg :: ~UchEventMsg () { } /*?nodoc?*/ bool UchEventMsg :: Activate (UchMsgStream& s, bool) { UchService* svc = (UchService*) &s; svc->PutEvent (this); return true; } /*?class UchGenMsg This is a sample derived class of \typ{UchEventMsg}. It defines events that contain a pointer to a \typ{UchMessage}. This message must be allocated dynamically because it is deleted by the destructor. The virtual functions \fun{ReadFrom} and \fun{WriteTo} are defined to act upon the message stored in the event. The following example fetches a word from the input buffer, creates a message depending on its value (\typ{FOO\_MSG} and \typ{BAR\_MSG} have been derived from \typ{UchMessage}), and transfers the data from the buffer to the event with \fun{Get}. This piece of code typically appears in the body of \fun{NewMessage}: \begin{ccode} UchGenMsg* ev = new UchGenMsg; sword type; if (! buf.Peek (&type)) return; switch (type) { case Foo : ev->SetMsg (new FOO_MSG); break; case Bar : ev->SetMsg (new BAR_MSG); break; ... } if (!buf.Get (ev)) // protocol error PutEvent (ev); \end{ccode} ?*/