1 //=============================================================================
3 * @file TkReactor_Test.cpp
5 * This is a simple test that illustrates the possibility to integrate
6 * ACE to the Tk Main Loop. This program uses ACE_TkReactor class to
7 * schedule three additional event sources:
8 * 1. Events from button "Stop Test" (registed with Tk_CreateEventHandler)
9 * 2. Events from button "Press Me" (registed with Tk_CreateEventHandler)
10 * 3. Events from X timer (registed with Tk_CreateTimerHandler)
11 * 4. Events from ACE timer (registed with ACE_TkReactor::schedule_timer)
12 * 5. Events from the TCP/IP channel using ACE_Acceptor
13 * No command line arguments are needed to run the test.
15 * @author Nagarajan Surendran <naga@cs.wustl.edu>
17 //=============================================================================
19 #include "test_config.h"
21 #include "ace/Event_Handler.h"
22 #include "ace/Acceptor.h"
23 #include "ace/SOCK_Acceptor.h"
24 #include "ace/SOCK_Connector.h"
25 #include "ace/Service_Config.h"
26 #include "ace/Thread_Manager.h"
27 #include "ace/TkReactor/TkReactor.h"
28 #include "ace/OS_NS_unistd.h"
33 Tcl_Interp
* tcl_interp
;
34 void eval (const char *s
)
37 ACE_OS::strcpy (buf
,s
);
38 int st
= Tcl_GlobalEval(tcl_interp
,buf
);
41 int n
= ACE_OS::strlen(s
);
42 char *wrk
= new char[n
+ 80];
43 ACE_OS::snprintf (wrk
, n
+ 80, "tkerror \"%s\"", s
);
44 Tcl_GlobalEval(tcl_interp
, wrk
);
50 static const u_short SERV_TCP_PORT
= 6670;
52 // counter for events from "Press Me" button.
53 static int count1
= 0;
55 // counter for events from Tk Timer.
56 static int count2
= 0;
58 // counter for events from ACE Timer.
59 static int count3
= 0;
62 // Callback for "Stop Test" buton - quit the program.
64 Quit (ClientData
, XEvent
*)
66 ACE_DEBUG ((LM_DEBUG
,"Quit called\n"));
78 " (%P) Client: Starting...\n"));
80 ACE_SOCK_Stream stream
;
81 ACE_SOCK_Connector connector
;
82 ACE_OS::snprintf (buf
, 100, "Client: the life was good!");
84 mes_len
= (int) htonl (ACE_OS::strlen (buf
) + 1);
86 if (connector
.connect (stream
,
87 ACE_INET_Addr (SERV_TCP_PORT
,
88 ACE_DEFAULT_SERVER_HOST
)) == -1)
97 ACE_OS::strlen (buf
) + 1) == -1)
103 if (stream
.close () == -1)
104 ACE_ERROR ((LM_ERROR
,
108 ACE_DEBUG ((LM_DEBUG
,
109 "(%P) Client: Message has been sent, about to exit...\n"));
113 // Callback for "Press Me" button.
116 #if TK_MAJOR_VERSION == 8 && TK_MINOR_VERSION > 3
117 inc_count (ClientData client_data
, Tcl_Interp
*interp
,int, const char **)
119 inc_count (ClientData client_data
, Tcl_Interp
*interp
,int, char **)
122 ACE_DEBUG ((LM_DEBUG
,"inc_count "));
125 ACE_OS::snprintf (new_string
, 80, "Events: [%d] [%d] [%d]",
126 count1
++, count2
, count3
);
128 // sprintf (command,"set %s %s",(char *)client_data,new_string);
130 const char *varValue
= Tcl_SetVar (interp
,(char *)client_data
,new_string
,TCL_LEAVE_ERR_MSG
);
136 // Callback for X Timer.
139 inc_tmo (ClientData client_data
)
145 ACE_OS::snprintf (new_string
, 80, "Events: [%d] [%d] [%d]",
146 count1
, count2
++, count3
);
148 // sprintf (command,"set %s %s",(char *)client_data,new_string);
150 const char *varValue
= Tcl_SetVar (tcl_interp
,(char *)client_data
,new_string
,TCL_LEAVE_ERR_MSG
);
152 ACE_ERROR ((LM_ERROR
,"Tcl_SetVar failed in inc_tmo\n"));
154 (void) Tk_CreateTimerHandler (1000,
159 class EV_handler
: public ACE_Event_Handler
162 virtual int handle_timeout (const ACE_Time_Value
&,
166 ACE_OS::snprintf (new_string
, 80, "Events: [%d] [%d] [%d]",
167 count1
, count2
, count3
++);
169 // sprintf (command,"set %s %s",(char *)arg,new_string);
171 const char *varValue
= Tcl_SetVar (tcl_interp
,(char *)arg
,new_string
,TCL_LEAVE_ERR_MSG
);
173 ACE_ERROR_RETURN ((LM_ERROR
,"Tcl_SetVar failed in handle_timeout\n"),-1);
179 class Connection_Handler
: public ACE_Svc_Handler
<ACE_SOCK_STREAM
, ACE_NULL_SYNCH
>
182 //FUZZ: disable check_for_lack_ACE_OS
183 virtual int open (void *)
185 //FUZZ: enable check_for_lack_ACE_OS
188 ssize_t ret
= this->peer ().recv_n ((char *) &head
,
190 if (ret
!= sizeof (int))
191 ACE_ERROR_RETURN ((LM_ERROR
,
196 ret
= this->peer ().recv_n (buf
,
199 if (ret
!= (int) ntohl (head
))
200 ACE_ERROR_RETURN ((LM_ERROR
,
204 ACE_DEBUG ((LM_DEBUG
,
205 " (%P)Server (ACE_SOCKET channel message): [%s]\n",
212 init (Tcl_Interp
*interp
)
214 if (Tcl_Init (interp
) == TCL_ERROR
)
216 if (Tk_Init (interp
) == TCL_ERROR
)
222 run_main (int, ACE_TCHAR
*[])
224 ACE_START_TEST (ACE_TEXT ("TkReactor_Test"));
226 tcl_interp
= Tcl_CreateInterp ();
228 if (init (tcl_interp
) != TCL_OK
) {
233 tk
= Tk_MainWindow(tcl_interp
);
236 ACE_ERROR_RETURN ((LM_ERROR
, "Tk_Reactor_Test: Tk_MainWindow() failed\n"),1);
239 char tcl_cmd
[] = "source TkReactor_Test.tcl";
240 if (Tcl_Eval (tcl_interp
, tcl_cmd
) != TCL_OK
) {
244 char label_var_name
[] = "label_var";
245 char pressme
[] = "pressme";
246 Tcl_CreateCommand (tcl_interp
,
252 // Register callback for X Timer
253 (void) Tk_CreateTimerHandler (1000,
257 // It will perform Tk Main Loop
258 ACE_TkReactor reactor
;
259 ACE_Reactor
r (&reactor
);
261 //Event Handler for ACE Timer.
264 ACE_Acceptor
<Connection_Handler
, ACE_SOCK_ACCEPTOR
> acceptor
;
266 if (acceptor
.open (ACE_INET_Addr ((u_short
) SERV_TCP_PORT
),
268 ACE_ERROR_RETURN ((LM_ERROR
,
273 if (reactor
.schedule_timer (&evh
,
274 (const void *) "label_var",
276 ACE_Time_Value (2))==-1)
277 ACE_ERROR_RETURN ((LM_ERROR
,
278 " (%P|%t) can't register with reactor\n"),
281 ACE_Thread_Manager::instance ()->spawn ((ACE_THR_FUNC
) client
,
283 THR_NEW_LWP
| THR_DETACHED
);
287 int result
= reactor
.handle_events ();
291 // ACE_DEBUG ((LM_DEBUG,"handle_events timed out\n"));
294 ACE_DEBUG ((LM_DEBUG
,"handle_events returned -1\n"));