// $Header$ #ifndef agent_h #define agent_h #include "Stmt.h" class Value; class Sequencer; class Frame; class Task; class Agent; struct foobar { int a; int b; } foobar; declare(List,string); typedef List(string) string_list; declare(PList,Agent); typedef PList(Agent) agent_list; class Notifiee { public: Notifiee( Stmt* arg_stmt, Frame* arg_frame ); ~Notifiee(); Stmt* stmt; Frame* frame; }; declare(PList,Notifiee); typedef PList(Notifiee) notification_list; declare(PDict,notification_list); typedef PDict(notification_list) notification_dict; class Agent : public GlishObject { public: Agent( Sequencer* s ); ~Agent(); // Send the given event/value list or pair to the event agent. // If is_request is true then this is a request/response event, // and the response value is returned; otherwise nil is returned. // If log is true and the sequencer is logging events, then // the event is logged. virtual Value* SendEvent( const char* event_name, parameter_list* args, int is_request, int log ) = 0; // Same for an event with just one value. void SendSingleValueEvent( const char* event_name, const Value* value, int log ); // Creates a event/value pair associated with this agent (the // event is not sent to the associated agent). Returns true // if there was some interest in the event, false otherwise. virtual int CreateEvent( const char* event_name, Value* event_value ); // Register the given statement as being interested in events // generated by this event agent. If field is non-null then only // the event .field is of interest; if is_copy is true then // the string "field" is the event agent's own copy (and thus // should be deleted when the event agent is). void RegisterInterest( Notifiee* notifiee, const char* field = 0, int is_copy = 0 ); // True if the given statement has expressed interested in // this Agent for the given field (or for all fields). int HasRegisteredInterest( Stmt* stmt, const char* field ); // Returns a Value object listing this agent's "whenever" // statements. The value consists of a record with two fields, // "event", which is a string array of event names, and // "stmt", the indices of the corresponding "whenever" statements. // Note that "event" might include more than one entry with the // same name; the pairs are unique, though. // // The special event name "*" corresponds to statements interested // in all events this agent generates (e.g., "whenever foo->* do ..."). // // The return Value should be Unref()'d when done with it. Value* AssociatedStatements(); // Return the Task version of this Agent, or nil if this // agent is not a task. virtual Task* AgentTask(); const char* AgentID() { return agent_ID; } Value* AgentRecord() { return agent_value; } void DescribeSelf( ostream& s ) const; protected: Value* BuildEventValue( parameter_list* args, int use_refs ); // Queues notification of those parties interested in the given // .field event, where "value" is the value associated with the // event. // // Returns true if there were some such parties, false otherwise. int NotifyInterestedParties( const char* field, Value* value ); // Queues notification of the given Notifiee, if it's active. Returns // true if the Notifiee was active, false otherwise. int DoNotification( Notifiee* n, const char* field, Value* value ); // Returns true if the given statement is on the given notification // list, false otherwise. int SearchNotificationList( notification_list* list, Stmt* stmt ); Sequencer* sequencer; notification_dict interested_parties; string_list* string_copies; const char* agent_ID; Value* agent_value; }; class UserAgent : public Agent { public: UserAgent( Sequencer* s ) : Agent(s) { } // Send an event with the given name and associated values // to the associated user agent. Value* SendEvent( const char* event_name, parameter_list* args, int is_request, int log ); }; // Agents currently in existence. extern agent_list agents; #endif /* agent_h */