home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 1999 mARCH / PCWK3A99.iso / Linux / DDD331 / DDD-3_1_.000 / DDD-3_1_ / ddd-3.1.1 / ddd / AsyncAgent.h < prev    next >
C/C++ Source or Header  |  1998-10-01  |  8KB  |  299 lines

  1. // $Id: AsyncAgent.h,v 1.21 1998/10/01 19:12:57 zeller Exp $
  2. // Asynchron Agent Interface
  3.  
  4. // Copyright (C) 1995-1998 Technische Universitaet Braunschweig, Germany.
  5. // Written by Andreas Zeller <zeller@ips.cs.tu-bs.de>.
  6. // 
  7. // This file is part of DDD.
  8. // 
  9. // DDD is free software; you can redistribute it and/or
  10. // modify it under the terms of the GNU General Public
  11. // License as published by the Free Software Foundation; either
  12. // version 2 of the License, or (at your option) any later version.
  13. // 
  14. // DDD is distributed in the hope that it will be useful,
  15. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  17. // See the GNU General Public License for more details.
  18. // 
  19. // You should have received a copy of the GNU General Public
  20. // License along with DDD -- see the file COPYING.
  21. // If not, write to the Free Software Foundation, Inc.,
  22. // 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  23. // 
  24. // DDD is the data display debugger.
  25. // For details, see the DDD World-Wide-Web page, 
  26. // `http://www.cs.tu-bs.de/softech/ddd/',
  27. // or send a mail to the DDD developers <ddd@ips.cs.tu-bs.de>.
  28.  
  29. #ifndef _DDD_AsyncAgent_h
  30. #define _DDD_AsyncAgent_h
  31.  
  32. #ifdef __GNUG__
  33. #pragma interface
  34. #endif
  35.  
  36. /*
  37.     AsyncAgent(app_context, p)
  38.     opens a three-way communication channel to the agent p (see Agent).
  39.  
  40.     In order to cooperate with other event-driven libraries (especially X),
  41.     communication is handled asynchronously: every time that input data
  42.     (from the agent's stdout) or error data (from the agent's stderr)
  43.     is available, an input handler is called passing the agent as parameter.
  44.  
  45.     The outputHandler is called whenever the agent is ready to read data
  46.     from its stdin. Its use is discouraged, since on some operating systems
  47.     the outputHandler is called even when the agent is not ready yet.
  48.  
  49.     Upon terminate(), the agent is killed asynchronously, i.e. terminate()
  50.     does not wait for the agent to die.
  51.  
  52.     Handlers are declared with addHandler().
  53.  
  54.     Asynchronus communication is implemented using XtAppAddInput(3).
  55. */
  56.  
  57.  
  58. #include "assert.h"
  59. #include <X11/Intrinsic.h>
  60. #include "Agent.h"
  61.  
  62. // Set to 1 if you want asynchronous notification
  63. // #define ASYNC_CHILD_STATUS_CHANGE
  64.  
  65. #ifndef ASYNC_CHILD_STATUS_CHANGE
  66. #define ASYNC_CHILD_STATUS_CHANGE (XtSpecificationRelease >= 6)
  67. #endif // !defined(ASYNC_CHILD_STATUS_CHANGE)
  68.  
  69.  
  70. class AsyncAgent;
  71.  
  72. typedef void (*AsyncAgentHandler)(AsyncAgent *agent);
  73.  
  74. struct AsyncAgentWorkProcInfo {
  75.     DECLARE_TYPE_INFO
  76.  
  77.     AsyncAgent *agent;
  78.     unsigned int type;
  79.     void *call_data;
  80.  
  81.     AsyncAgentWorkProcInfo(AsyncAgent *a, unsigned t, void *c)
  82.     : agent(a), type(t), call_data(c)
  83.     {}
  84.  
  85. private:
  86.     AsyncAgentWorkProcInfo(const AsyncAgentWorkProcInfo&)
  87.     : agent(0), type(0), call_data(0)
  88.     {
  89.     assert(0);
  90.     }
  91.     AsyncAgentWorkProcInfo& operator = (const AsyncAgentWorkProcInfo&)
  92.     {
  93.     assert(0); return *this;
  94.     }
  95. };
  96.  
  97. struct AsyncAgentWorkProc {
  98.     DECLARE_TYPE_INFO
  99.  
  100.     XtWorkProcId proc_id;             // id of running background proc
  101.     AsyncAgentWorkProcInfo *info;    // info
  102.     AsyncAgentWorkProc *next;        // next one
  103.  
  104.     // Constructor
  105.     AsyncAgentWorkProc(XtWorkProcId i, AsyncAgentWorkProcInfo *inf,
  106.                AsyncAgentWorkProc *n):
  107.     proc_id(i), info(inf), next(n)
  108.     {}
  109.  
  110. private:
  111.     AsyncAgentWorkProc(const AsyncAgentWorkProc& p)
  112.     : proc_id(p.proc_id), info(0), next(0)
  113.     {
  114.     assert(0);
  115.     }
  116.     AsyncAgentWorkProc& operator = (const AsyncAgentWorkProc&)
  117.     {
  118.     assert(0); return *this;
  119.     }
  120. };
  121.  
  122. // Events
  123. const unsigned AsyncAgent_NTypes = Agent_NTypes;
  124.  
  125. // Handlers
  126. const unsigned OutputReady     = 0;    // agent is ready for data
  127. const unsigned InputReady      = 1;    // data from agent's stdout is ready
  128. const unsigned ErrorReady      = 2;    // data from agent's stdin is ready
  129. const unsigned OutputException = 3;    // I/O exception (urgent msg) on output
  130. const unsigned InputException  = 4;    // I/O exception (urgent msg) on input
  131. const unsigned ErrorException  = 5;    // I/O exception (urgent msg) on error
  132.  
  133. const unsigned AsyncAgent_NHandlers = 6; // # of handler types
  134.  
  135. class AsyncAgent: public Agent {
  136. public:
  137.     DECLARE_TYPE_INFO
  138.  
  139. private:
  140.  
  141.     XtAppContext _appContext;        // the application context
  142.  
  143.     AsyncAgentHandler _handlers[AsyncAgent_NHandlers]; // handlers
  144.     XtInputId _ids[AsyncAgent_NHandlers];           // their ids
  145.  
  146.     AsyncAgentWorkProc *workProcs;    // working procedures
  147.  
  148.     // dispatch event
  149.     void dispatch(int *fid, XtInputId *id);
  150.  
  151.     // used in childStatusChange()
  152.     int new_status;
  153.     bool status_change_pending;
  154.  
  155. #if ASYNC_CHILD_STATUS_CHANGE
  156.     XtSignalId signal_id;
  157. #else
  158.     XtIntervalId signal_id;        // Just for padding
  159. #endif
  160.  
  161.     bool killing_asynchronously;
  162.  
  163.     void initHandlers();
  164.     void addDeathOfChildHandler();
  165.  
  166.     // delete remaining work procedure(s)
  167.     void deleteWorkProc(AsyncAgentWorkProcInfo *info, bool remove = true);
  168.     void deleteAllWorkProcs();
  169.  
  170.     // Call when NEW_STATUS has been set
  171.     void statusChange();
  172.  
  173. #if ASYNC_CHILD_STATUS_CHANGE
  174.     static void _childStatusChange(XtPointer client_data, XtSignalId *id);
  175. #endif
  176.  
  177.     // X Event Handlers
  178.     static void somethingHappened(XtPointer client_data,
  179.                   int *fid, XtInputId *id);
  180.     static void childStatusChange(Agent *agent, void *client_data,
  181.                   void *call_data);
  182.     static Boolean callTheHandlers(XtPointer client_data);
  183.     static void callTheHandlersIfIdle(XtPointer client_data, XtIntervalId *id);
  184.  
  185.     // Helping functions
  186.     static void terminateProcess(XtPointer, XtIntervalId *);
  187.     static void hangupProcess(XtPointer, XtIntervalId *);
  188.     static void killProcess(XtPointer, XtIntervalId *);
  189.  
  190. protected:
  191.     // Set handler
  192.     AsyncAgentHandler setHandler(unsigned type, AsyncAgentHandler handler = 0);
  193.  
  194.     // Clear all handlers
  195.     void clearHandlers();
  196.  
  197.     // resources
  198.     XtInputId id(unsigned type)
  199.     {
  200.     assert(type < AsyncAgent_NHandlers);
  201.     return _ids[type]; 
  202.     }
  203.  
  204.     AsyncAgentHandler handler(unsigned type)
  205.     {
  206.     assert(type < AsyncAgent_NHandlers);
  207.     return _handlers[type];
  208.     }
  209.  
  210.     virtual void waitToTerminate();
  211.  
  212.     // Delayed event handling
  213.     virtual void callHandlersWhenIdle(int type, void *call_data = 0);
  214.     virtual bool isIdle() { return true; }
  215.  
  216.     // Hook for channel closing
  217.     virtual void closeChannel(FILE *fp);
  218.  
  219. private:
  220.     // remove input
  221.     void removeInput(unsigned type)
  222.     {
  223.     if (id(type))
  224.     {
  225.         XtRemoveInput(id(type));
  226.             _ids[type] = 0;
  227.         }
  228.     }
  229.  
  230.     AsyncAgent& operator = (const AsyncAgent&)
  231.     {
  232.     assert(0);
  233.     return *this;
  234.     }
  235.  
  236. public:
  237.     // Resources
  238.     XtAppContext appContext() const { return _appContext; }
  239.  
  240.     // Constructors
  241.     AsyncAgent(XtAppContext app_context, const string& pth, 
  242.            unsigned nTypes = AsyncAgent_NTypes):
  243.     Agent(pth, nTypes), _appContext(app_context), workProcs(0), 
  244.     new_status(0), status_change_pending(false), 
  245.     signal_id(0), killing_asynchronously(false)
  246.     {
  247.     initHandlers();
  248.     addDeathOfChildHandler();
  249.     }
  250.  
  251.     AsyncAgent(XtAppContext app_context, FILE *in = stdin, FILE *out = stdout,
  252.     FILE *err = 0, unsigned nTypes = AsyncAgent_NTypes):
  253.     Agent(in, out, err, nTypes), _appContext(app_context), workProcs(0),
  254.     new_status(0), status_change_pending(false),
  255.     signal_id(0), killing_asynchronously(false)
  256.     {
  257.     initHandlers();
  258.     }
  259.  
  260.     AsyncAgent(XtAppContext app_context, bool dummy,
  261.     unsigned nTypes = AsyncAgent_NTypes):
  262.     Agent(dummy, nTypes), _appContext(app_context), workProcs(0),
  263.     new_status(0), status_change_pending(false),
  264.     signal_id(0), killing_asynchronously(false)
  265.     {
  266.     initHandlers();
  267.     }
  268.  
  269.     // Duplicator
  270.     AsyncAgent(const AsyncAgent& c):
  271.     Agent(c), _appContext(c.appContext()), workProcs(0), 
  272.     new_status(0), status_change_pending(false),
  273.     signal_id(0), killing_asynchronously(false)
  274.     {
  275.     initHandlers();
  276.     }
  277.     virtual Agent *dup() const { return new AsyncAgent(*this); }
  278.  
  279.     // Destructor
  280.     ~AsyncAgent()
  281.     {
  282.     // Make sure the work procedure won't be called
  283.     deleteAllWorkProcs();
  284.  
  285.     // Inhibit further Xt selection
  286.     clearHandlers();
  287.     }
  288.  
  289.     // Commit pending status changes
  290.     virtual void commit();
  291.  
  292.     // These need special management:
  293.     virtual void abort();
  294.     virtual void terminate(bool onExit = false);
  295. };
  296.  
  297. #endif // _DDD_AsyncAgent_h
  298. // DON'T ADD ANYTHING BEHIND THIS #endif
  299.