summaryrefslogtreecommitdiff
path: root/ACE/examples
diff options
context:
space:
mode:
authorWilliam R. Otte <wotte@dre.vanderbilt.edu>2006-07-24 15:50:30 +0000
committerWilliam R. Otte <wotte@dre.vanderbilt.edu>2006-07-24 15:50:30 +0000
commitc44379cc7d9c7aa113989237ab0f56db12aa5219 (patch)
tree66a84b20d47f2269d8bdc6e0323f338763424d3a /ACE/examples
parent3aff90f4a822fcf5d902bbfbcc9fa931d6191a8c (diff)
downloadATCD-c44379cc7d9c7aa113989237ab0f56db12aa5219.tar.gz
Repo restructuring
Diffstat (limited to 'ACE/examples')
-rw-r--r--ACE/examples/APG/Active_Objects/.cvsignore4
-rw-r--r--ACE/examples/APG/Active_Objects/AO.cpp186
-rw-r--r--ACE/examples/APG/Active_Objects/AO2.cpp196
-rw-r--r--ACE/examples/APG/Active_Objects/Makefile.am56
-rw-r--r--ACE/examples/APG/Active_Objects/active_objects.mpc18
-rw-r--r--ACE/examples/APG/Config/.cvsignore6
-rw-r--r--ACE/examples/APG/Config/ARGV_Example.cpp62
-rw-r--r--ACE/examples/APG/Config/Get_Opt.cpp59
-rw-r--r--ACE/examples/APG/Config/Get_Opt_Long.cpp48
-rw-r--r--ACE/examples/APG/Config/HASTATUS_export.h54
-rw-r--r--ACE/examples/APG/Config/HA_Status.cpp98
-rw-r--r--ACE/examples/APG/Config/Makefile.am81
-rw-r--r--ACE/examples/APG/Config/config.mpc31
-rw-r--r--ACE/examples/APG/Containers/.cvsignore24
-rw-r--r--ACE/examples/APG/Containers/Allocator.cpp93
-rw-r--r--ACE/examples/APG/Containers/Array.cpp41
-rw-r--r--ACE/examples/APG/Containers/DLList.cpp116
-rw-r--r--ACE/examples/APG/Containers/DataElement.h52
-rw-r--r--ACE/examples/APG/Containers/Hash_Map.cpp118
-rw-r--r--ACE/examples/APG/Containers/Hash_Map_Hash.cpp111
-rw-r--r--ACE/examples/APG/Containers/Hash_Map_Hash.h57
-rw-r--r--ACE/examples/APG/Containers/KeyType.h28
-rw-r--r--ACE/examples/APG/Containers/Makefile.am223
-rw-r--r--ACE/examples/APG/Containers/Map_Manager.cpp117
-rw-r--r--ACE/examples/APG/Containers/Map_Manager_Specialization.cpp153
-rw-r--r--ACE/examples/APG/Containers/Queues.cpp115
-rw-r--r--ACE/examples/APG/Containers/RB_Tree.cpp135
-rw-r--r--ACE/examples/APG/Containers/RB_Tree_Functors.cpp134
-rw-r--r--ACE/examples/APG/Containers/RB_Tree_Functors.h37
-rw-r--r--ACE/examples/APG/Containers/Sets.cpp123
-rw-r--r--ACE/examples/APG/Containers/Stacks.cpp147
-rw-r--r--ACE/examples/APG/Containers/containers.mpc87
-rw-r--r--ACE/examples/APG/Logging/.cvsignore36
-rw-r--r--ACE/examples/APG/Logging/Callback-2.h44
-rw-r--r--ACE/examples/APG/Logging/Callback-3.h69
-rw-r--r--ACE/examples/APG/Logging/Callback.h25
-rw-r--r--ACE/examples/APG/Logging/Change_Instance_Default.cpp37
-rw-r--r--ACE/examples/APG/Logging/Change_Mask.cpp29
-rw-r--r--ACE/examples/APG/Logging/Howto_Syslog.cpp28
-rw-r--r--ACE/examples/APG/Logging/LogManager.h102
-rw-r--r--ACE/examples/APG/Logging/Log_Msg_Alt.h19
-rw-r--r--ACE/examples/APG/Logging/Makefile.am362
-rw-r--r--ACE/examples/APG/Logging/Simple1.cpp23
-rw-r--r--ACE/examples/APG/Logging/Simple2.cpp25
-rw-r--r--ACE/examples/APG/Logging/Trace.h153
-rw-r--r--ACE/examples/APG/Logging/Trace_Return.cpp41
-rw-r--r--ACE/examples/APG/Logging/Use_Callback.cpp20
-rw-r--r--ACE/examples/APG/Logging/Use_Callback2.cpp20
-rw-r--r--ACE/examples/APG/Logging/Use_LogManager.cpp33
-rw-r--r--ACE/examples/APG/Logging/Use_Logger.cpp17
-rw-r--r--ACE/examples/APG/Logging/Use_Logging_Server.cpp20
-rw-r--r--ACE/examples/APG/Logging/Use_Logging_Strategy.cpp33
-rw-r--r--ACE/examples/APG/Logging/Use_Multiple_Sinks.cpp34
-rw-r--r--ACE/examples/APG/Logging/Use_Ostream.cpp36
-rw-r--r--ACE/examples/APG/Logging/Use_Stderr.cpp38
-rw-r--r--ACE/examples/APG/Logging/Use_Syslog.cpp32
-rw-r--r--ACE/examples/APG/Logging/Wrap_Macros.cpp38
-rw-r--r--ACE/examples/APG/Logging/Wrap_Macros_Alt.cpp18
-rw-r--r--ACE/examples/APG/Logging/client.conf1
-rw-r--r--ACE/examples/APG/Logging/logging.mpc128
-rw-r--r--ACE/examples/APG/Logging/logging_strategy.conf1
-rw-r--r--ACE/examples/APG/Logging/server.conf3
-rw-r--r--ACE/examples/APG/Makefile.am31
-rw-r--r--ACE/examples/APG/Misc_IPC/.cvsignore6
-rw-r--r--ACE/examples/APG/Misc_IPC/Makefile.am69
-rw-r--r--ACE/examples/APG/Misc_IPC/UDP_Broadcast.cpp34
-rw-r--r--ACE/examples/APG/Misc_IPC/UDP_Multicast.cpp37
-rw-r--r--ACE/examples/APG/Misc_IPC/UDP_Unicast.cpp71
-rw-r--r--ACE/examples/APG/Misc_IPC/misc_ipc.mpc25
-rw-r--r--ACE/examples/APG/Naming/.cvsignore10
-rw-r--r--ACE/examples/APG/Naming/EMail.h28
-rw-r--r--ACE/examples/APG/Naming/Graph.cpp47
-rw-r--r--ACE/examples/APG/Naming/Graph.h18
-rw-r--r--ACE/examples/APG/Naming/Graphable_Element.cpp4
-rw-r--r--ACE/examples/APG/Naming/Graphable_Element.h53
-rw-r--r--ACE/examples/APG/Naming/Makefile.am123
-rw-r--r--ACE/examples/APG/Naming/Name_Binding.h61
-rw-r--r--ACE/examples/APG/Naming/Naming_Context.h68
-rw-r--r--ACE/examples/APG/Naming/Netlocal.cpp40
-rw-r--r--ACE/examples/APG/Naming/Netlocal_reader.cpp23
-rw-r--r--ACE/examples/APG/Naming/Nodelocal.cpp37
-rw-r--r--ACE/examples/APG/Naming/Nodelocal_shared.cpp43
-rw-r--r--ACE/examples/APG/Naming/Nodelocal_shared_reader.cpp23
-rw-r--r--ACE/examples/APG/Naming/Temperature_Grapher.cpp81
-rw-r--r--ACE/examples/APG/Naming/Temperature_Grapher.h30
-rw-r--r--ACE/examples/APG/Naming/Temperature_Grapher_Options.h21
-rw-r--r--ACE/examples/APG/Naming/Temperature_Monitor.cpp133
-rw-r--r--ACE/examples/APG/Naming/Temperature_Monitor.h29
-rw-r--r--ACE/examples/APG/Naming/Temperature_Monitor2.cpp145
-rw-r--r--ACE/examples/APG/Naming/Temperature_Monitor2.h36
-rw-r--r--ACE/examples/APG/Naming/Temperature_Monitor_Options.h48
-rw-r--r--ACE/examples/APG/Naming/Thermometer.h48
-rw-r--r--ACE/examples/APG/Naming/naming.mpc50
-rw-r--r--ACE/examples/APG/Naming/svc.conf1
-rw-r--r--ACE/examples/APG/Proactor/.cvsignore2
-rw-r--r--ACE/examples/APG/Proactor/HA_Proactive_Status.cpp163
-rw-r--r--ACE/examples/APG/Proactor/HA_Proactive_Status.h87
-rw-r--r--ACE/examples/APG/Proactor/Makefile.am39
-rw-r--r--ACE/examples/APG/Proactor/proactor.mpc10
-rw-r--r--ACE/examples/APG/Processes/.cvsignore8
-rw-r--r--ACE/examples/APG/Processes/Makefile.am90
-rw-r--r--ACE/examples/APG/Processes/Process_Manager_Death.cpp67
-rw-r--r--ACE/examples/APG/Processes/Process_Manager_Spawn.cpp59
-rw-r--r--ACE/examples/APG/Processes/Process_Mutex.cpp79
-rw-r--r--ACE/examples/APG/Processes/Spawn.cpp206
-rw-r--r--ACE/examples/APG/Processes/processes.mpc34
-rw-r--r--ACE/examples/APG/Reactor/.cvsignore16
-rw-r--r--ACE/examples/APG/Reactor/Client.cpp118
-rw-r--r--ACE/examples/APG/Reactor/Client.h52
-rw-r--r--ACE/examples/APG/Reactor/ClientService.h40
-rw-r--r--ACE/examples/APG/Reactor/HAStatus-AC.cpp139
-rw-r--r--ACE/examples/APG/Reactor/HAStatus.cpp332
-rw-r--r--ACE/examples/APG/Reactor/Makefile.am139
-rw-r--r--ACE/examples/APG/Reactor/Reschedule.cpp83
-rw-r--r--ACE/examples/APG/Reactor/Schedule_Timers.cpp65
-rw-r--r--ACE/examples/APG/Reactor/Timer_Cancel.cpp106
-rw-r--r--ACE/examples/APG/Reactor/Timer_State_Data.cpp153
-rw-r--r--ACE/examples/APG/Reactor/Timers.cpp81
-rw-r--r--ACE/examples/APG/Reactor/reactor.mpc58
-rw-r--r--ACE/examples/APG/Shared_Memory/.cvsignore10
-rw-r--r--ACE/examples/APG/Shared_Memory/Hash_Map.cpp250
-rw-r--r--ACE/examples/APG/Shared_Memory/Makefile.am112
-rw-r--r--ACE/examples/APG/Shared_Memory/Malloc.cpp113
-rw-r--r--ACE/examples/APG/Shared_Memory/Mem_Map.cpp35
-rw-r--r--ACE/examples/APG/Shared_Memory/PI_Malloc.cpp140
-rw-r--r--ACE/examples/APG/Shared_Memory/Pool_Growth.cpp261
-rw-r--r--ACE/examples/APG/Shared_Memory/Record.h45
-rw-r--r--ACE/examples/APG/Shared_Memory/shared_memory.mpc42
-rw-r--r--ACE/examples/APG/Signals/.cvsignore10
-rw-r--r--ACE/examples/APG/Signals/Makefile.am85
-rw-r--r--ACE/examples/APG/Signals/SigAction.cpp75
-rw-r--r--ACE/examples/APG/Signals/SigGuard.cpp43
-rw-r--r--ACE/examples/APG/Signals/SigHandler.cpp60
-rw-r--r--ACE/examples/APG/Signals/SigHandlers.cpp54
-rw-r--r--ACE/examples/APG/Signals/SigInfo.cpp167
-rw-r--r--ACE/examples/APG/Signals/signals.mpc37
-rw-r--r--ACE/examples/APG/Sockets/.cvsignore8
-rw-r--r--ACE/examples/APG/Sockets/Basic.cpp35
-rw-r--r--ACE/examples/APG/Sockets/Basic_Robust.cpp137
-rw-r--r--ACE/examples/APG/Sockets/Iovec.cpp84
-rw-r--r--ACE/examples/APG/Sockets/Makefile.am72
-rw-r--r--ACE/examples/APG/Sockets/Server.cpp95
-rw-r--r--ACE/examples/APG/Sockets/sockets.mpc30
-rw-r--r--ACE/examples/APG/Streams/.cvsignore2
-rw-r--r--ACE/examples/APG/Streams/Answerer.cpp403
-rw-r--r--ACE/examples/APG/Streams/BasicTask.h143
-rw-r--r--ACE/examples/APG/Streams/Command.h40
-rw-r--r--ACE/examples/APG/Streams/CommandModule.cpp20
-rw-r--r--ACE/examples/APG/Streams/CommandModule.h27
-rw-r--r--ACE/examples/APG/Streams/CommandStream.cpp97
-rw-r--r--ACE/examples/APG/Streams/CommandStream.h44
-rw-r--r--ACE/examples/APG/Streams/CommandTask.cpp153
-rw-r--r--ACE/examples/APG/Streams/CommandTask.h39
-rw-r--r--ACE/examples/APG/Streams/CommandTasks.cpp221
-rw-r--r--ACE/examples/APG/Streams/CommandTasks.h108
-rw-r--r--ACE/examples/APG/Streams/EndTask.h27
-rw-r--r--ACE/examples/APG/Streams/Makefile.am52
-rw-r--r--ACE/examples/APG/Streams/Message.h92
-rw-r--r--ACE/examples/APG/Streams/MessageInfo.h100
-rw-r--r--ACE/examples/APG/Streams/RecordingDevice.h119
-rw-r--r--ACE/examples/APG/Streams/RecordingDeviceFactory.cpp25
-rw-r--r--ACE/examples/APG/Streams/RecordingDeviceFactory.h22
-rw-r--r--ACE/examples/APG/Streams/RecordingDevice_QC.h5
-rw-r--r--ACE/examples/APG/Streams/RecordingDevice_Text.cpp197
-rw-r--r--ACE/examples/APG/Streams/RecordingDevice_Text.h84
-rw-r--r--ACE/examples/APG/Streams/RecordingDevice_USRVM.h5
-rw-r--r--ACE/examples/APG/Streams/Util.h92
-rw-r--r--ACE/examples/APG/Streams/streams.mpc17
-rw-r--r--ACE/examples/APG/Svc_Config/.cvsignore4
-rw-r--r--ACE/examples/APG/Svc_Config/HASTATUS_export.h53
-rw-r--r--ACE/examples/APG/Svc_Config/HA_Configurable_Server_Dynamic.cpp17
-rw-r--r--ACE/examples/APG/Svc_Config/HA_Configurable_Server_Static.cpp18
-rw-r--r--ACE/examples/APG/Svc_Config/HA_Status_Dynamic.cpp113
-rw-r--r--ACE/examples/APG/Svc_Config/HA_Status_Dynamic.h43
-rw-r--r--ACE/examples/APG/Svc_Config/HA_Status_Static.cpp121
-rw-r--r--ACE/examples/APG/Svc_Config/HA_Status_Static.h40
-rw-r--r--ACE/examples/APG/Svc_Config/Makefile.am80
-rw-r--r--ACE/examples/APG/Svc_Config/status.ini2
-rw-r--r--ACE/examples/APG/Svc_Config/svc.conf.dynamic2
-rw-r--r--ACE/examples/APG/Svc_Config/svc.conf.static1
-rw-r--r--ACE/examples/APG/Svc_Config/svc_config.mpc28
-rw-r--r--ACE/examples/APG/ThreadManagement/.cvsignore18
-rw-r--r--ACE/examples/APG/ThreadManagement/Async_Cancel.cpp63
-rw-r--r--ACE/examples/APG/ThreadManagement/Coop_Cancel.cpp68
-rw-r--r--ACE/examples/APG/ThreadManagement/ExitHandler.cpp71
-rw-r--r--ACE/examples/APG/ThreadManagement/Makefile.am146
-rw-r--r--ACE/examples/APG/ThreadManagement/Pool.cpp46
-rw-r--r--ACE/examples/APG/ThreadManagement/Priorities.cpp104
-rw-r--r--ACE/examples/APG/ThreadManagement/SecurityContext.h16
-rw-r--r--ACE/examples/APG/ThreadManagement/Signals.cpp93
-rw-r--r--ACE/examples/APG/ThreadManagement/Signals2.cpp97
-rw-r--r--ACE/examples/APG/ThreadManagement/Start_Hook.cpp60
-rw-r--r--ACE/examples/APG/ThreadManagement/State.cpp39
-rw-r--r--ACE/examples/APG/ThreadManagement/threadmgmt.mpc65
-rw-r--r--ACE/examples/APG/ThreadPools/.cvsignore10
-rw-r--r--ACE/examples/APG/ThreadPools/Futures.cpp321
-rw-r--r--ACE/examples/APG/ThreadPools/LF_ThreadPool.cpp252
-rw-r--r--ACE/examples/APG/ThreadPools/Makefile.am96
-rw-r--r--ACE/examples/APG/ThreadPools/Request_Handler.h34
-rw-r--r--ACE/examples/APG/ThreadPools/TP_Reactor.cpp269
-rw-r--r--ACE/examples/APG/ThreadPools/Task_ThreadPool.cpp149
-rw-r--r--ACE/examples/APG/ThreadPools/ThreadPool.cpp271
-rw-r--r--ACE/examples/APG/ThreadPools/threadpools.mpc38
-rw-r--r--ACE/examples/APG/ThreadSafety/.cvsignore16
-rw-r--r--ACE/examples/APG/ThreadSafety/Atomic_Op.cpp127
-rw-r--r--ACE/examples/APG/ThreadSafety/Barrier.cpp91
-rw-r--r--ACE/examples/APG/ThreadSafety/ClientContext.h30
-rw-r--r--ACE/examples/APG/ThreadSafety/Makefile.am141
-rw-r--r--ACE/examples/APG/ThreadSafety/Mutex.cpp73
-rw-r--r--ACE/examples/APG/ThreadSafety/RW_Lock.cpp139
-rw-r--r--ACE/examples/APG/ThreadSafety/Semaphore.cpp147
-rw-r--r--ACE/examples/APG/ThreadSafety/TSS.cpp75
-rw-r--r--ACE/examples/APG/ThreadSafety/Tokens.cpp102
-rw-r--r--ACE/examples/APG/ThreadSafety/Tokens_Deadlock.cpp69
-rw-r--r--ACE/examples/APG/ThreadSafety/threadsafety.mpc60
-rw-r--r--ACE/examples/APG/Threads/.cvsignore12
-rw-r--r--ACE/examples/APG/Threads/Activate.cpp33
-rw-r--r--ACE/examples/APG/Threads/Condition_Variables.cpp118
-rw-r--r--ACE/examples/APG/Threads/Guards.cpp95
-rw-r--r--ACE/examples/APG/Threads/Makefile.am104
-rw-r--r--ACE/examples/APG/Threads/Message_Blocks.cpp50
-rw-r--r--ACE/examples/APG/Threads/Message_Queue.cpp179
-rw-r--r--ACE/examples/APG/Threads/Message_Receiver.h90
-rw-r--r--ACE/examples/APG/Threads/Mutexes.cpp75
-rw-r--r--ACE/examples/APG/Threads/threads.mpc44
-rw-r--r--ACE/examples/APG/Timers/.cvsignore8
-rw-r--r--ACE/examples/APG/Timers/Alarm.cpp57
-rw-r--r--ACE/examples/APG/Timers/CB.cpp70
-rw-r--r--ACE/examples/APG/Timers/CB.h36
-rw-r--r--ACE/examples/APG/Timers/Makefile.am91
-rw-r--r--ACE/examples/APG/Timers/PCB.cpp79
-rw-r--r--ACE/examples/APG/Timers/PCB.h29
-rw-r--r--ACE/examples/APG/Timers/PTimerDispatcher.cpp69
-rw-r--r--ACE/examples/APG/Timers/PTimerDispatcher.h39
-rw-r--r--ACE/examples/APG/Timers/Task.cpp73
-rw-r--r--ACE/examples/APG/Timers/TimerDispatcher.cpp73
-rw-r--r--ACE/examples/APG/Timers/TimerDispatcher.h40
-rw-r--r--ACE/examples/APG/Timers/Timers.cpp58
-rw-r--r--ACE/examples/APG/Timers/Upcall.cpp172
-rw-r--r--ACE/examples/APG/Timers/Upcall.h87
-rw-r--r--ACE/examples/APG/Timers/timers.mpc34
-rw-r--r--ACE/examples/ASX/.cvsignore1
-rw-r--r--ACE/examples/ASX/CCM_App/.cvsignore4
-rw-r--r--ACE/examples/ASX/CCM_App/ASX_CCM_App.mpc26
-rw-r--r--ACE/examples/ASX/CCM_App/CCM_App.cpp119
-rw-r--r--ACE/examples/ASX/CCM_App/Makefile.am57
-rw-r--r--ACE/examples/ASX/CCM_App/SC_Client.cpp13
-rw-r--r--ACE/examples/ASX/CCM_App/SC_Server.cpp86
-rw-r--r--ACE/examples/ASX/CCM_App/svc.conf21
-rw-r--r--ACE/examples/ASX/CCM_App/svc.conf.xml33
-rw-r--r--ACE/examples/ASX/Event_Server/Event_Server/Consumer_Router.cpp159
-rw-r--r--ACE/examples/ASX/Event_Server/Event_Server/Consumer_Router.h71
-rw-r--r--ACE/examples/ASX/Event_Server/Event_Server/Event.mpc15
-rw-r--r--ACE/examples/ASX/Event_Server/Event_Server/Event_Analyzer.cpp80
-rw-r--r--ACE/examples/ASX/Event_Server/Event_Server/Event_Analyzer.h44
-rw-r--r--ACE/examples/ASX/Event_Server/Event_Server/Makefile.am49
-rw-r--r--ACE/examples/ASX/Event_Server/Event_Server/Options.cpp206
-rw-r--r--ACE/examples/ASX/Event_Server/Event_Server/Options.h122
-rw-r--r--ACE/examples/ASX/Event_Server/Event_Server/Options.i141
-rw-r--r--ACE/examples/ASX/Event_Server/Event_Server/Peer_Router.cpp435
-rw-r--r--ACE/examples/ASX/Event_Server/Event_Server/Peer_Router.h158
-rw-r--r--ACE/examples/ASX/Event_Server/Event_Server/Supplier_Router.cpp165
-rw-r--r--ACE/examples/ASX/Event_Server/Event_Server/Supplier_Router.h72
-rw-r--r--ACE/examples/ASX/Event_Server/Event_Server/event_server.cpp258
-rw-r--r--ACE/examples/ASX/Event_Server/Makefile.am14
-rw-r--r--ACE/examples/ASX/Event_Server/README79
-rw-r--r--ACE/examples/ASX/Event_Server/Transceiver/Makefile.am34
-rw-r--r--ACE/examples/ASX/Event_Server/Transceiver/Transceiver.mpc9
-rw-r--r--ACE/examples/ASX/Event_Server/Transceiver/transceiver.cpp238
-rw-r--r--ACE/examples/ASX/Event_Server/Transceiver/transceiver.h60
-rw-r--r--ACE/examples/ASX/Makefile.am16
-rw-r--r--ACE/examples/ASX/Message_Queue/.cvsignore6
-rw-r--r--ACE/examples/ASX/Message_Queue/ASX_Message_Queue.mpc25
-rw-r--r--ACE/examples/ASX/Message_Queue/Makefile.am64
-rw-r--r--ACE/examples/ASX/Message_Queue/bounded_buffer.cpp140
-rw-r--r--ACE/examples/ASX/Message_Queue/buffer_stream.cpp311
-rw-r--r--ACE/examples/ASX/Message_Queue/priority_buffer.cpp145
-rw-r--r--ACE/examples/ASX/UPIPE_Event_Server/Consumer_Router.cpp138
-rw-r--r--ACE/examples/ASX/UPIPE_Event_Server/Consumer_Router.h53
-rw-r--r--ACE/examples/ASX/UPIPE_Event_Server/Event_Analyzer.cpp73
-rw-r--r--ACE/examples/ASX/UPIPE_Event_Server/Event_Analyzer.h37
-rw-r--r--ACE/examples/ASX/UPIPE_Event_Server/Makefile.am49
-rw-r--r--ACE/examples/ASX/UPIPE_Event_Server/Options.cpp207
-rw-r--r--ACE/examples/ASX/UPIPE_Event_Server/Options.h88
-rw-r--r--ACE/examples/ASX/UPIPE_Event_Server/Options.i166
-rw-r--r--ACE/examples/ASX/UPIPE_Event_Server/Peer_Router.cpp283
-rw-r--r--ACE/examples/ASX/UPIPE_Event_Server/Peer_Router.h127
-rw-r--r--ACE/examples/ASX/UPIPE_Event_Server/Supplier_Router.cpp137
-rw-r--r--ACE/examples/ASX/UPIPE_Event_Server/Supplier_Router.h57
-rw-r--r--ACE/examples/ASX/UPIPE_Event_Server/UPIPE_Event.mpc15
-rw-r--r--ACE/examples/ASX/UPIPE_Event_Server/event_server.cpp269
-rw-r--r--ACE/examples/Bounded_Packet_Relay/.cvsignore2
-rw-r--r--ACE/examples/Bounded_Packet_Relay/BPR_Drivers.cpp535
-rw-r--r--ACE/examples/Bounded_Packet_Relay/BPR_Drivers.h290
-rw-r--r--ACE/examples/Bounded_Packet_Relay/BPR_Drivers_T.cpp322
-rw-r--r--ACE/examples/Bounded_Packet_Relay/BPR_Drivers_T.h178
-rw-r--r--ACE/examples/Bounded_Packet_Relay/Bounded_Packet_Relay.mpc7
-rw-r--r--ACE/examples/Bounded_Packet_Relay/Makefile.am39
-rw-r--r--ACE/examples/Bounded_Packet_Relay/README194
-rw-r--r--ACE/examples/Bounded_Packet_Relay/Thread_Bounded_Packet_Relay.cpp770
-rw-r--r--ACE/examples/Bounded_Packet_Relay/Thread_Bounded_Packet_Relay.h400
-rw-r--r--ACE/examples/Bounded_Packet_Relay/bpr_thread.cpp122
-rw-r--r--ACE/examples/C++NPv1/.cvsignore14
-rw-r--r--ACE/examples/C++NPv1/C++NPv1.mpc70
-rw-r--r--ACE/examples/C++NPv1/Iterative_Logging_Server.cpp17
-rw-r--r--ACE/examples/C++NPv1/Iterative_Logging_Server.h64
-rw-r--r--ACE/examples/C++NPv1/Logging_Client.cpp141
-rw-r--r--ACE/examples/C++NPv1/Logging_Handler.cpp110
-rw-r--r--ACE/examples/C++NPv1/Logging_Handler.h55
-rw-r--r--ACE/examples/C++NPv1/Logging_Server.cpp74
-rw-r--r--ACE/examples/C++NPv1/Logging_Server.h44
-rw-r--r--ACE/examples/C++NPv1/Makefile.am191
-rw-r--r--ACE/examples/C++NPv1/Process_Per_Connection_Logging_Server.cpp180
-rw-r--r--ACE/examples/C++NPv1/Process_Per_Connection_Logging_Server.h53
-rw-r--r--ACE/examples/C++NPv1/README73
-rw-r--r--ACE/examples/C++NPv1/RT_Thread_Per_Connection_Logging_Server.cpp132
-rw-r--r--ACE/examples/C++NPv1/RT_Thread_Per_Connection_Logging_Server.h22
-rw-r--r--ACE/examples/C++NPv1/Reactive_Logging_Server.cpp17
-rw-r--r--ACE/examples/C++NPv1/Reactive_Logging_Server.h79
-rw-r--r--ACE/examples/C++NPv1/Reactive_Logging_Server_Ex.cpp20
-rw-r--r--ACE/examples/C++NPv1/Reactive_Logging_Server_Ex.h95
-rw-r--r--ACE/examples/C++NPv1/Thread_Per_Connection_Logging_Server.cpp93
-rw-r--r--ACE/examples/C++NPv1/Thread_Per_Connection_Logging_Server.h49
-rw-r--r--ACE/examples/C++NPv2/.cvsignore14
-rw-r--r--ACE/examples/C++NPv2/AC_CLD_export.h54
-rw-r--r--ACE/examples/C++NPv2/AC_Client_Logging_Daemon.cpp426
-rw-r--r--ACE/examples/C++NPv2/AC_Client_Logging_Daemon.h62
-rw-r--r--ACE/examples/C++NPv2/AIO_CLD_export.h54
-rw-r--r--ACE/examples/C++NPv2/AIO_Client_Logging_Daemon.cpp360
-rw-r--r--ACE/examples/C++NPv2/AIO_Client_Logging_Daemon.h135
-rw-r--r--ACE/examples/C++NPv2/C++NPv2.mpc183
-rw-r--r--ACE/examples/C++NPv2/CLD_export.h38
-rw-r--r--ACE/examples/C++NPv2/Client_Logging_Daemon.cpp379
-rw-r--r--ACE/examples/C++NPv2/Configurable_Logging_Server.cpp20
-rw-r--r--ACE/examples/C++NPv2/Logging_Acceptor.cpp38
-rw-r--r--ACE/examples/C++NPv2/Logging_Acceptor.h53
-rw-r--r--ACE/examples/C++NPv2/Logging_Acceptor_Ex.h41
-rw-r--r--ACE/examples/C++NPv2/Logging_Event_Handler.cpp45
-rw-r--r--ACE/examples/C++NPv2/Logging_Event_Handler.h61
-rw-r--r--ACE/examples/C++NPv2/Logging_Event_Handler_Ex.cpp41
-rw-r--r--ACE/examples/C++NPv2/Logging_Event_Handler_Ex.h57
-rw-r--r--ACE/examples/C++NPv2/Logging_Handler.cpp110
-rw-r--r--ACE/examples/C++NPv2/Logging_Handler.h57
-rw-r--r--ACE/examples/C++NPv2/Makefile.am424
-rw-r--r--ACE/examples/C++NPv2/README99
-rw-r--r--ACE/examples/C++NPv2/Reactor_Logging_Server.cpp29
-rw-r--r--ACE/examples/C++NPv2/Reactor_Logging_Server_Adapter.cpp69
-rw-r--r--ACE/examples/C++NPv2/Reactor_Logging_Server_Adapter.h35
-rw-r--r--ACE/examples/C++NPv2/Reactor_Logging_Server_T.cpp26
-rw-r--r--ACE/examples/C++NPv2/Reactor_Logging_Server_T.h29
-rw-r--r--ACE/examples/C++NPv2/SLD.cpp17
-rw-r--r--ACE/examples/C++NPv2/SLDEX_export.h38
-rw-r--r--ACE/examples/C++NPv2/SLD_export.h38
-rw-r--r--ACE/examples/C++NPv2/SLDex.cpp17
-rw-r--r--ACE/examples/C++NPv2/SR_Configurable_Logging_Server.cpp26
-rw-r--r--ACE/examples/C++NPv2/Select_Reactor_Logging_Server.cpp105
-rw-r--r--ACE/examples/C++NPv2/Server_Shutdown.cpp98
-rw-r--r--ACE/examples/C++NPv2/Service_Reporter.cpp125
-rw-r--r--ACE/examples/C++NPv2/Service_Reporter.h38
-rw-r--r--ACE/examples/C++NPv2/TPCLS_export.h54
-rw-r--r--ACE/examples/C++NPv2/TPC_Logging_Server.cpp106
-rw-r--r--ACE/examples/C++NPv2/TPC_Logging_Server.h87
-rw-r--r--ACE/examples/C++NPv2/TPLS_export.h38
-rw-r--r--ACE/examples/C++NPv2/TP_Logging_Server.cpp70
-rw-r--r--ACE/examples/C++NPv2/TP_Logging_Server.h131
-rw-r--r--ACE/examples/C++NPv2/TP_Reactor_Logging_Server.cpp117
-rw-r--r--ACE/examples/C++NPv2/WFMO_Reactor_Logging_Server.cpp145
-rw-r--r--ACE/examples/C++NPv2/display_logfile.cpp361
-rw-r--r--ACE/examples/C++NPv2/svc.conf8
-rw-r--r--ACE/examples/ConfigViewer/ConfigTreeCtrl.cpp229
-rw-r--r--ACE/examples/ConfigViewer/ConfigTreeCtrl.h52
-rw-r--r--ACE/examples/ConfigViewer/ConfigViewer.mpc7
-rw-r--r--ACE/examples/ConfigViewer/ConfigurationViewer.cpp45
-rw-r--r--ACE/examples/ConfigViewer/ConfigurationViewer.rc9
-rw-r--r--ACE/examples/ConfigViewer/MainFrame.cpp199
-rw-r--r--ACE/examples/ConfigViewer/MainFrame.h72
-rw-r--r--ACE/examples/ConfigViewer/README74
-rw-r--r--ACE/examples/ConfigViewer/ValueDlg.cpp63
-rw-r--r--ACE/examples/ConfigViewer/ValueDlg.h51
-rw-r--r--ACE/examples/ConfigViewer/ValueListCtrl.cpp227
-rw-r--r--ACE/examples/ConfigViewer/ValueListCtrl.h47
-rw-r--r--ACE/examples/ConfigViewer/mondrian.icobin0 -> 766 bytes
-rw-r--r--ACE/examples/ConfigViewer/mondrian.xpm44
-rw-r--r--ACE/examples/ConfigViewer/stdafx.cpp3
-rw-r--r--ACE/examples/ConfigViewer/stdafx.h16
-rw-r--r--ACE/examples/Connection/Makefile.am15
-rw-r--r--ACE/examples/Connection/blocking/.cvsignore4
-rw-r--r--ACE/examples/Connection/blocking/Connection_Blocking.mpc21
-rw-r--r--ACE/examples/Connection/blocking/Makefile.am60
-rw-r--r--ACE/examples/Connection/blocking/README36
-rw-r--r--ACE/examples/Connection/blocking/SPIPE-acceptor.cpp224
-rw-r--r--ACE/examples/Connection/blocking/SPIPE-acceptor.h79
-rw-r--r--ACE/examples/Connection/blocking/SPIPE-connector.cpp219
-rw-r--r--ACE/examples/Connection/blocking/SPIPE-connector.h82
-rw-r--r--ACE/examples/Connection/blocking/test_spipe_acceptor.cpp36
-rw-r--r--ACE/examples/Connection/blocking/test_spipe_connector.cpp21
-rw-r--r--ACE/examples/Connection/misc/.cvsignore4
-rw-r--r--ACE/examples/Connection/misc/Connection_Handler.cpp226
-rw-r--r--ACE/examples/Connection/misc/Connection_Handler.h44
-rw-r--r--ACE/examples/Connection/misc/Connection_Misc.mpc17
-rw-r--r--ACE/examples/Connection/misc/Makefile.am53
-rw-r--r--ACE/examples/Connection/misc/test_upipe.cpp122
-rw-r--r--ACE/examples/Connection/misc/test_upipe.h76
-rw-r--r--ACE/examples/Connection/non_blocking/.cvsignore16
-rw-r--r--ACE/examples/Connection/non_blocking/CPP-acceptor.cpp247
-rw-r--r--ACE/examples/Connection/non_blocking/CPP-acceptor.h96
-rw-r--r--ACE/examples/Connection/non_blocking/CPP-connector.cpp289
-rw-r--r--ACE/examples/Connection/non_blocking/CPP-connector.h98
-rw-r--r--ACE/examples/Connection/non_blocking/Connection_Non_Blocking.mpc68
-rw-r--r--ACE/examples/Connection/non_blocking/Makefile.am150
-rw-r--r--ACE/examples/Connection/non_blocking/README28
-rw-r--r--ACE/examples/Connection/non_blocking/test_lsock_acceptor.cpp49
-rw-r--r--ACE/examples/Connection/non_blocking/test_lsock_connector.cpp46
-rw-r--r--ACE/examples/Connection/non_blocking/test_sock_acceptor.cpp34
-rw-r--r--ACE/examples/Connection/non_blocking/test_sock_connector.cpp49
-rw-r--r--ACE/examples/Connection/non_blocking/test_spipe_acceptor.cpp45
-rw-r--r--ACE/examples/Connection/non_blocking/test_spipe_connector.cpp40
-rw-r--r--ACE/examples/Connection/non_blocking/test_tli_acceptor.cpp41
-rw-r--r--ACE/examples/Connection/non_blocking/test_tli_connector.cpp39
-rw-r--r--ACE/examples/DLL/.cvsignore2
-rw-r--r--ACE/examples/DLL/DLL.mpc22
-rw-r--r--ACE/examples/DLL/Magazine.h42
-rw-r--r--ACE/examples/DLL/Makefile.am64
-rw-r--r--ACE/examples/DLL/Newsweek.cpp55
-rw-r--r--ACE/examples/DLL/Newsweek.h59
-rw-r--r--ACE/examples/DLL/README47
-rw-r--r--ACE/examples/DLL/Today.cpp55
-rw-r--r--ACE/examples/DLL/Today.h60
-rw-r--r--ACE/examples/DLL/test_dll.cpp90
-rw-r--r--ACE/examples/Export/.cvsignore2
-rw-r--r--ACE/examples/Export/Export.mpc19
-rw-r--r--ACE/examples/Export/Makefile.am51
-rw-r--r--ACE/examples/Export/README7
-rw-r--r--ACE/examples/Export/dll.cpp27
-rw-r--r--ACE/examples/Export/dll.h69
-rwxr-xr-xACE/examples/Export/run_test.pl17
-rw-r--r--ACE/examples/Export/test.cpp64
-rw-r--r--ACE/examples/Export/test_export.h44
-rw-r--r--ACE/examples/IOStream/Makefile.am14
-rw-r--r--ACE/examples/IOStream/README22
-rw-r--r--ACE/examples/IOStream/client/.cvsignore2
-rw-r--r--ACE/examples/IOStream/client/IOStream_Client.mpc5
-rw-r--r--ACE/examples/IOStream/client/Makefile.am30
-rw-r--r--ACE/examples/IOStream/client/iostream_client.cpp71
-rw-r--r--ACE/examples/IOStream/server/.cvsignore2
-rw-r--r--ACE/examples/IOStream/server/IOStream_Server.mpc5
-rw-r--r--ACE/examples/IOStream/server/Makefile.am33
-rw-r--r--ACE/examples/IOStream/server/iostream_server.cpp132
-rw-r--r--ACE/examples/IOStream/server/iostream_server.h53
-rw-r--r--ACE/examples/IPC_SAP/ATM_SAP/.cvsignore4
-rw-r--r--ACE/examples/IPC_SAP/ATM_SAP/CPP-client.cpp202
-rw-r--r--ACE/examples/IPC_SAP/ATM_SAP/CPP-server.cpp156
-rw-r--r--ACE/examples/IPC_SAP/ATM_SAP/Makefile.am46
-rw-r--r--ACE/examples/IPC_SAP/ATM_SAP/atm_sap.mpc16
-rw-r--r--ACE/examples/IPC_SAP/DEV_SAP/Makefile.am14
-rw-r--r--ACE/examples/IPC_SAP/DEV_SAP/README23
-rw-r--r--ACE/examples/IPC_SAP/DEV_SAP/reader/.cvsignore2
-rw-r--r--ACE/examples/IPC_SAP/DEV_SAP/reader/Makefile.am38
-rw-r--r--ACE/examples/IPC_SAP/DEV_SAP/reader/dev_sap_reader.mpc11
-rw-r--r--ACE/examples/IPC_SAP/DEV_SAP/reader/reader.cpp69
-rw-r--r--ACE/examples/IPC_SAP/DEV_SAP/writer/.cvsignore2
-rw-r--r--ACE/examples/IPC_SAP/DEV_SAP/writer/Makefile.am38
-rw-r--r--ACE/examples/IPC_SAP/DEV_SAP/writer/dev_sap_writer.mpc11
-rw-r--r--ACE/examples/IPC_SAP/DEV_SAP/writer/writer.cpp77
-rw-r--r--ACE/examples/IPC_SAP/FIFO_SAP/.cvsignore10
-rw-r--r--ACE/examples/IPC_SAP/FIFO_SAP/FIFO-Msg-client.cpp43
-rw-r--r--ACE/examples/IPC_SAP/FIFO_SAP/FIFO-Msg-server.cpp49
-rw-r--r--ACE/examples/IPC_SAP/FIFO_SAP/FIFO-client.cpp29
-rw-r--r--ACE/examples/IPC_SAP/FIFO_SAP/FIFO-server.cpp30
-rw-r--r--ACE/examples/IPC_SAP/FIFO_SAP/FIFO-test.cpp122
-rw-r--r--ACE/examples/IPC_SAP/FIFO_SAP/Makefile.am98
-rw-r--r--ACE/examples/IPC_SAP/FIFO_SAP/fifo_sap.mpc42
-rw-r--r--ACE/examples/IPC_SAP/FILE_SAP/.cvsignore2
-rw-r--r--ACE/examples/IPC_SAP/FILE_SAP/Makefile.am38
-rw-r--r--ACE/examples/IPC_SAP/FILE_SAP/client.cpp90
-rw-r--r--ACE/examples/IPC_SAP/FILE_SAP/file_sap_client.mpc11
-rw-r--r--ACE/examples/IPC_SAP/FILE_SAP/testfile1
-rw-r--r--ACE/examples/IPC_SAP/Makefile.am21
-rw-r--r--ACE/examples/IPC_SAP/SOCK_SAP/.cvsignore18
-rw-r--r--ACE/examples/IPC_SAP/SOCK_SAP/C-inclient.cpp84
-rw-r--r--ACE/examples/IPC_SAP/SOCK_SAP/C-inserver.cpp116
-rw-r--r--ACE/examples/IPC_SAP/SOCK_SAP/CPP-inclient.cpp424
-rw-r--r--ACE/examples/IPC_SAP/SOCK_SAP/CPP-inclient.h108
-rw-r--r--ACE/examples/IPC_SAP/SOCK_SAP/CPP-inserver-fancy.cpp582
-rw-r--r--ACE/examples/IPC_SAP/SOCK_SAP/CPP-inserver-fancy.h43
-rw-r--r--ACE/examples/IPC_SAP/SOCK_SAP/CPP-inserver-poll.cpp207
-rw-r--r--ACE/examples/IPC_SAP/SOCK_SAP/CPP-inserver.cpp391
-rw-r--r--ACE/examples/IPC_SAP/SOCK_SAP/CPP-memclient.cpp53
-rw-r--r--ACE/examples/IPC_SAP/SOCK_SAP/CPP-memserver.cpp70
-rw-r--r--ACE/examples/IPC_SAP/SOCK_SAP/CPP-unclient.cpp71
-rw-r--r--ACE/examples/IPC_SAP/SOCK_SAP/CPP-unserver.cpp159
-rw-r--r--ACE/examples/IPC_SAP/SOCK_SAP/FD-unclient.cpp60
-rw-r--r--ACE/examples/IPC_SAP/SOCK_SAP/FD-unserver.cpp100
-rw-r--r--ACE/examples/IPC_SAP/SOCK_SAP/Makefile.am179
-rw-r--r--ACE/examples/IPC_SAP/SOCK_SAP/README46
-rw-r--r--ACE/examples/IPC_SAP/SOCK_SAP/local_data1
-rwxr-xr-xACE/examples/IPC_SAP/SOCK_SAP/run_test36
-rw-r--r--ACE/examples/IPC_SAP/SOCK_SAP/sock_sap.mpc72
-rwxr-xr-xACE/examples/IPC_SAP/SOCK_SAP/summarize45
-rw-r--r--ACE/examples/IPC_SAP/SPIPE_SAP/.cvsignore16
-rw-r--r--ACE/examples/IPC_SAP/SPIPE_SAP/Makefile.am132
-rw-r--r--ACE/examples/IPC_SAP/SPIPE_SAP/NPClient.cpp62
-rw-r--r--ACE/examples/IPC_SAP/SPIPE_SAP/NPServer.cpp67
-rw-r--r--ACE/examples/IPC_SAP/SPIPE_SAP/SPIPE_SAP.mpc58
-rw-r--r--ACE/examples/IPC_SAP/SPIPE_SAP/client.cpp48
-rw-r--r--ACE/examples/IPC_SAP/SPIPE_SAP/consumer_msg.cpp59
-rw-r--r--ACE/examples/IPC_SAP/SPIPE_SAP/consumer_read.cpp56
-rw-r--r--ACE/examples/IPC_SAP/SPIPE_SAP/producer_msg.cpp66
-rw-r--r--ACE/examples/IPC_SAP/SPIPE_SAP/producer_read.cpp54
-rw-r--r--ACE/examples/IPC_SAP/SPIPE_SAP/server.cpp124
-rw-r--r--ACE/examples/IPC_SAP/SPIPE_SAP/shared.h10
-rw-r--r--ACE/examples/IPC_SAP/SSL_SAP/Makefile.am196
-rw-r--r--ACE/examples/IPC_SAP/SSL_SAP/README17
-rw-r--r--ACE/examples/IPC_SAP/SSL_SAP/SSL-client-simple.cpp377
-rw-r--r--ACE/examples/IPC_SAP/SSL_SAP/SSL-client-simple.h98
-rw-r--r--ACE/examples/IPC_SAP/SSL_SAP/SSL-client.cpp418
-rw-r--r--ACE/examples/IPC_SAP/SSL_SAP/SSL-client.h111
-rw-r--r--ACE/examples/IPC_SAP/SSL_SAP/SSL-server-fancy.cpp606
-rw-r--r--ACE/examples/IPC_SAP/SSL_SAP/SSL-server-fancy.h44
-rw-r--r--ACE/examples/IPC_SAP/SSL_SAP/SSL-server-poll.cpp212
-rw-r--r--ACE/examples/IPC_SAP/SSL_SAP/SSL-server-simple.cpp366
-rw-r--r--ACE/examples/IPC_SAP/SSL_SAP/SSL-server.cpp430
-rw-r--r--ACE/examples/IPC_SAP/SSL_SAP/SSL_SAP.mpc44
-rw-r--r--ACE/examples/IPC_SAP/SSL_SAP/dummy.pem15
-rw-r--r--ACE/examples/IPC_SAP/SSL_SAP/key.pem15
-rw-r--r--ACE/examples/IPC_SAP/SSL_SAP/local_data1
-rwxr-xr-xACE/examples/IPC_SAP/SSL_SAP/summarize45
-rw-r--r--ACE/examples/IPC_SAP/TLI_SAP/.cvsignore16
-rw-r--r--ACE/examples/IPC_SAP/TLI_SAP/CPP-ATM-client.cpp162
-rw-r--r--ACE/examples/IPC_SAP/TLI_SAP/CPP-ATM-server.cpp114
-rw-r--r--ACE/examples/IPC_SAP/TLI_SAP/CPP-client.cpp94
-rw-r--r--ACE/examples/IPC_SAP/TLI_SAP/CPP-server.cpp89
-rw-r--r--ACE/examples/IPC_SAP/TLI_SAP/Makefile.am124
-rw-r--r--ACE/examples/IPC_SAP/TLI_SAP/TLI_SAP.mpc58
-rw-r--r--ACE/examples/IPC_SAP/TLI_SAP/db-client.cpp60
-rw-r--r--ACE/examples/IPC_SAP/TLI_SAP/db-server.cpp121
-rw-r--r--ACE/examples/IPC_SAP/TLI_SAP/ftp-client.cpp54
-rw-r--r--ACE/examples/IPC_SAP/TLI_SAP/ftp-server.cpp83
-rw-r--r--ACE/examples/IPC_SAP/UPIPE_SAP/.cvsignore6
-rw-r--r--ACE/examples/IPC_SAP/UPIPE_SAP/Makefile.am73
-rw-r--r--ACE/examples/IPC_SAP/UPIPE_SAP/UPIPE_SAP.mpc26
-rw-r--r--ACE/examples/IPC_SAP/UPIPE_SAP/ex1.cpp183
-rw-r--r--ACE/examples/IPC_SAP/UPIPE_SAP/ex2.cpp179
-rw-r--r--ACE/examples/IPC_SAP/UPIPE_SAP/ex3.cpp159
-rw-r--r--ACE/examples/Log_Msg/.cvsignore6
-rw-r--r--ACE/examples/Log_Msg/Log_Msg.mpc23
-rw-r--r--ACE/examples/Log_Msg/Log_Msg_MFC/Log_Msg_MFC.cpp90
-rw-r--r--ACE/examples/Log_Msg/Log_Msg_MFC/Log_Msg_MFC.h62
-rw-r--r--ACE/examples/Log_Msg/Log_Msg_MFC/Log_Msg_MFC.mpc12
-rw-r--r--ACE/examples/Log_Msg/Log_Msg_MFC/Log_Msg_MFC.rc207
-rw-r--r--ACE/examples/Log_Msg/Log_Msg_MFC/Log_Msg_MFCDlg.cpp185
-rw-r--r--ACE/examples/Log_Msg/Log_Msg_MFC/Log_Msg_MFCDlg.h59
-rw-r--r--ACE/examples/Log_Msg/Log_Msg_MFC/MFC_Log.cpp45
-rw-r--r--ACE/examples/Log_Msg/Log_Msg_MFC/MFC_Log.h47
-rw-r--r--ACE/examples/Log_Msg/Log_Msg_MFC/README40
-rw-r--r--ACE/examples/Log_Msg/Log_Msg_MFC/Resource.h21
-rw-r--r--ACE/examples/Log_Msg/Log_Msg_MFC/StdAfx.cpp9
-rw-r--r--ACE/examples/Log_Msg/Log_Msg_MFC/StdAfx.h28
-rw-r--r--ACE/examples/Log_Msg/Log_Msg_MFC/res/Log_Msg_MFC.icobin0 -> 1078 bytes
-rw-r--r--ACE/examples/Log_Msg/Log_Msg_MFC/res/Log_Msg_MFC.rc213
-rw-r--r--ACE/examples/Log_Msg/Makefile.am59
-rw-r--r--ACE/examples/Log_Msg/README65
-rw-r--r--ACE/examples/Log_Msg/test_callback.cpp166
-rw-r--r--ACE/examples/Log_Msg/test_log_msg.cpp218
-rw-r--r--ACE/examples/Log_Msg/test_ostream.cpp89
-rw-r--r--ACE/examples/Logger/Acceptor-server/.cvsignore2
-rw-r--r--ACE/examples/Logger/Acceptor-server/Logger_Acceptor_Server.mpc6
-rw-r--r--ACE/examples/Logger/Acceptor-server/Makefile.am34
-rw-r--r--ACE/examples/Logger/Acceptor-server/server_loggerd.cpp241
-rw-r--r--ACE/examples/Logger/Acceptor-server/server_loggerd.h54
-rw-r--r--ACE/examples/Logger/Makefile.am15
-rw-r--r--ACE/examples/Logger/README32
-rw-r--r--ACE/examples/Logger/client/.cvsignore2
-rw-r--r--ACE/examples/Logger/client/Logger_client.mpc6
-rw-r--r--ACE/examples/Logger/client/Makefile.am33
-rw-r--r--ACE/examples/Logger/client/logging_app.cpp59
-rw-r--r--ACE/examples/Logger/simple-server/.cvsignore2
-rw-r--r--ACE/examples/Logger/simple-server/Logger_Simple_Server.mpc6
-rw-r--r--ACE/examples/Logger/simple-server/Logging_Acceptor.cpp85
-rw-r--r--ACE/examples/Logger/simple-server/Logging_Acceptor.h59
-rw-r--r--ACE/examples/Logger/simple-server/Logging_Handler.cpp164
-rw-r--r--ACE/examples/Logger/simple-server/Logging_Handler.h71
-rw-r--r--ACE/examples/Logger/simple-server/Makefile.am38
-rw-r--r--ACE/examples/Logger/simple-server/Reactor_Singleton.h33
-rw-r--r--ACE/examples/Logger/simple-server/server_loggerd.cpp85
-rw-r--r--ACE/examples/Makefile.am43
-rw-r--r--ACE/examples/Map_Manager/Makefile.am33
-rw-r--r--ACE/examples/Map_Manager/Map_Manager.mpc6
-rw-r--r--ACE/examples/Map_Manager/test_hash_map_manager.cpp80
-rw-r--r--ACE/examples/Mem_Map/IO-tests/.cvsignore2
-rw-r--r--ACE/examples/Mem_Map/IO-tests/IO_Test.cpp240
-rw-r--r--ACE/examples/Mem_Map/IO-tests/IO_Test.h100
-rw-r--r--ACE/examples/Mem_Map/IO-tests/Makefile.am40
-rw-r--r--ACE/examples/Mem_Map/IO-tests/Mem_Map_IO_Tests.mpc6
-rw-r--r--ACE/examples/Mem_Map/IO-tests/test_io.cpp211
-rw-r--r--ACE/examples/Mem_Map/Makefile.am14
-rw-r--r--ACE/examples/Mem_Map/file-reverse/.cvsignore1
-rw-r--r--ACE/examples/Mem_Map/file-reverse/Makefile.am38
-rw-r--r--ACE/examples/Mem_Map/file-reverse/Mem_Map_File_Reverse.mpc7
-rw-r--r--ACE/examples/Mem_Map/file-reverse/file-reverse.cpp59
-rw-r--r--ACE/examples/Misc/.cvsignore16
-rw-r--r--ACE/examples/Misc/Makefile.am191
-rw-r--r--ACE/examples/Misc/Misc.mpc66
-rw-r--r--ACE/examples/Misc/test_XtReactor1.cpp173
-rw-r--r--ACE/examples/Misc/test_XtReactor2.cpp101
-rw-r--r--ACE/examples/Misc/test_dump.cpp33
-rw-r--r--ACE/examples/Misc/test_dump.h50
-rw-r--r--ACE/examples/Misc/test_get_opt.cpp54
-rw-r--r--ACE/examples/Misc/test_profile_timer.cpp38
-rw-r--r--ACE/examples/Misc/test_read_buffer.cpp34
-rw-r--r--ACE/examples/Misc/test_set.cpp57
-rw-r--r--ACE/examples/Misc/test_sstring.cpp26
-rw-r--r--ACE/examples/Misc/test_trace.cpp114
-rw-r--r--ACE/examples/NT_Service/Makefile.am44
-rw-r--r--ACE/examples/NT_Service/NT_Service.mpc7
-rw-r--r--ACE/examples/NT_Service/README45
-rw-r--r--ACE/examples/NT_Service/main.cpp256
-rw-r--r--ACE/examples/NT_Service/ntsvc.cpp113
-rw-r--r--ACE/examples/NT_Service/ntsvc.h65
-rw-r--r--ACE/examples/Naming/.cvsignore4
-rw-r--r--ACE/examples/Naming/Makefile.am90
-rw-r--r--ACE/examples/Naming/Naming.mpc34
-rw-r--r--ACE/examples/Naming/test_multiple_contexts.cpp86
-rw-r--r--ACE/examples/Naming/test_non_existent.cpp54
-rw-r--r--ACE/examples/Naming/test_open.cpp83
-rw-r--r--ACE/examples/Naming/test_writers.cpp76
-rw-r--r--ACE/examples/OS/Makefile.am13
-rw-r--r--ACE/examples/OS/Process/.cvsignore4
-rw-r--r--ACE/examples/OS/Process/Makefile.am52
-rw-r--r--ACE/examples/OS/Process/OS_Process.mpc16
-rw-r--r--ACE/examples/OS/Process/README54
-rw-r--r--ACE/examples/OS/Process/imore.cpp267
-rw-r--r--ACE/examples/OS/Process/process.cpp577
-rw-r--r--ACE/examples/QOS/Change_Receiver_FlowSpec/Fill_ACE_QoS.cpp99
-rw-r--r--ACE/examples/QOS/Change_Receiver_FlowSpec/Fill_ACE_QoS.h76
-rw-r--r--ACE/examples/QOS/Change_Receiver_FlowSpec/FlowSpec_Dbase.h52
-rw-r--r--ACE/examples/QOS/Change_Receiver_FlowSpec/Makefile.am76
-rw-r--r--ACE/examples/QOS/Change_Receiver_FlowSpec/QOS_Change_Receiver_FlowSpec.mpc25
-rw-r--r--ACE/examples/QOS/Change_Receiver_FlowSpec/QoS_Signal_Handler.cpp34
-rw-r--r--ACE/examples/QOS/Change_Receiver_FlowSpec/QoS_Signal_Handler.h45
-rw-r--r--ACE/examples/QOS/Change_Receiver_FlowSpec/QoS_Util.cpp122
-rw-r--r--ACE/examples/QOS/Change_Receiver_FlowSpec/QoS_Util.h75
-rw-r--r--ACE/examples/QOS/Change_Receiver_FlowSpec/README127
-rw-r--r--ACE/examples/QOS/Change_Receiver_FlowSpec/Receiver_QoS_Event_Handler.cpp216
-rw-r--r--ACE/examples/QOS/Change_Receiver_FlowSpec/Receiver_QoS_Event_Handler.h61
-rw-r--r--ACE/examples/QOS/Change_Receiver_FlowSpec/Sender_QoS_Event_Handler.cpp146
-rw-r--r--ACE/examples/QOS/Change_Receiver_FlowSpec/Sender_QoS_Event_Handler.h61
-rw-r--r--ACE/examples/QOS/Change_Receiver_FlowSpec/receiver.cpp300
-rw-r--r--ACE/examples/QOS/Change_Receiver_FlowSpec/sender.cpp316
-rw-r--r--ACE/examples/QOS/Change_Sender_TSpec/Fill_ACE_QoS.cpp99
-rw-r--r--ACE/examples/QOS/Change_Sender_TSpec/Fill_ACE_QoS.h75
-rw-r--r--ACE/examples/QOS/Change_Sender_TSpec/FlowSpec_Dbase.h52
-rw-r--r--ACE/examples/QOS/Change_Sender_TSpec/Makefile.am76
-rw-r--r--ACE/examples/QOS/Change_Sender_TSpec/QOS_Change_Sender_TSpec.mpc25
-rw-r--r--ACE/examples/QOS/Change_Sender_TSpec/QoS_Signal_Handler.cpp34
-rw-r--r--ACE/examples/QOS/Change_Sender_TSpec/QoS_Signal_Handler.h45
-rw-r--r--ACE/examples/QOS/Change_Sender_TSpec/QoS_Util.cpp122
-rw-r--r--ACE/examples/QOS/Change_Sender_TSpec/QoS_Util.h75
-rw-r--r--ACE/examples/QOS/Change_Sender_TSpec/README126
-rw-r--r--ACE/examples/QOS/Change_Sender_TSpec/Receiver_QoS_Event_Handler.cpp145
-rw-r--r--ACE/examples/QOS/Change_Sender_TSpec/Receiver_QoS_Event_Handler.h61
-rw-r--r--ACE/examples/QOS/Change_Sender_TSpec/Sender_QoS_Event_Handler.cpp221
-rw-r--r--ACE/examples/QOS/Change_Sender_TSpec/Sender_QoS_Event_Handler.h61
-rw-r--r--ACE/examples/QOS/Change_Sender_TSpec/receiver.cpp319
-rw-r--r--ACE/examples/QOS/Change_Sender_TSpec/sender.cpp313
-rw-r--r--ACE/examples/QOS/Diffserv/Makefile.am62
-rw-r--r--ACE/examples/QOS/Diffserv/NOTES.txt58
-rw-r--r--ACE/examples/QOS/Diffserv/QOS_Diffserv.mpc18
-rw-r--r--ACE/examples/QOS/Diffserv/README107
-rw-r--r--ACE/examples/QOS/Diffserv/diffserv_test.cpp136
-rwxr-xr-xACE/examples/QOS/Diffserv/run_test.pl40
-rw-r--r--ACE/examples/QOS/Diffserv/server.cpp163
-rw-r--r--ACE/examples/QOS/Makefile.am16
-rw-r--r--ACE/examples/QOS/Simple/Fill_ACE_QoS.cpp99
-rw-r--r--ACE/examples/QOS/Simple/Fill_ACE_QoS.h75
-rw-r--r--ACE/examples/QOS/Simple/FlowSpec_Dbase.h52
-rw-r--r--ACE/examples/QOS/Simple/Makefile.am76
-rw-r--r--ACE/examples/QOS/Simple/QOS_Simple.mpc25
-rw-r--r--ACE/examples/QOS/Simple/QoS_Signal_Handler.cpp40
-rw-r--r--ACE/examples/QOS/Simple/QoS_Signal_Handler.h45
-rw-r--r--ACE/examples/QOS/Simple/QoS_Util.cpp122
-rw-r--r--ACE/examples/QOS/Simple/QoS_Util.h75
-rw-r--r--ACE/examples/QOS/Simple/README142
-rw-r--r--ACE/examples/QOS/Simple/Receiver_QoS_Event_Handler.cpp137
-rw-r--r--ACE/examples/QOS/Simple/Receiver_QoS_Event_Handler.h61
-rw-r--r--ACE/examples/QOS/Simple/Sender_QoS_Event_Handler.cpp144
-rw-r--r--ACE/examples/QOS/Simple/Sender_QoS_Event_Handler.h61
-rw-r--r--ACE/examples/QOS/Simple/receiver.cpp301
-rw-r--r--ACE/examples/QOS/Simple/sender.cpp315
-rw-r--r--ACE/examples/README77
-rw-r--r--ACE/examples/Reactor/Dgram/.cvsignore4
-rw-r--r--ACE/examples/Reactor/Dgram/CODgram.cpp254
-rw-r--r--ACE/examples/Reactor/Dgram/Dgram.cpp258
-rw-r--r--ACE/examples/Reactor/Dgram/Makefile.am51
-rw-r--r--ACE/examples/Reactor/Dgram/Reactor_Dgram.mpc18
-rw-r--r--ACE/examples/Reactor/FIFO/.cvsignore4
-rw-r--r--ACE/examples/Reactor/FIFO/Makefile.am56
-rw-r--r--ACE/examples/Reactor/FIFO/Reactor_FIFO.mpc18
-rw-r--r--ACE/examples/Reactor/FIFO/client.cpp23
-rw-r--r--ACE/examples/Reactor/FIFO/server.cpp89
-rw-r--r--ACE/examples/Reactor/Makefile.am20
-rw-r--r--ACE/examples/Reactor/Misc/.cvsignore16
-rw-r--r--ACE/examples/Reactor/Misc/Makefile.am137
-rw-r--r--ACE/examples/Reactor/Misc/Reactor_Misc.mpc57
-rw-r--r--ACE/examples/Reactor/Misc/notification.cpp385
-rw-r--r--ACE/examples/Reactor/Misc/pingpong.cpp302
-rw-r--r--ACE/examples/Reactor/Misc/test_demuxing.cpp384
-rw-r--r--ACE/examples/Reactor/Misc/test_early_timeouts.cpp114
-rw-r--r--ACE/examples/Reactor/Misc/test_event_handler_t.cpp47
-rw-r--r--ACE/examples/Reactor/Misc/test_reactors.cpp195
-rw-r--r--ACE/examples/Reactor/Misc/test_signals_1.cpp114
-rw-r--r--ACE/examples/Reactor/Misc/test_signals_2.cpp291
-rw-r--r--ACE/examples/Reactor/Misc/test_time_value.cpp83
-rw-r--r--ACE/examples/Reactor/Misc/test_timer_queue.cpp115
-rw-r--r--ACE/examples/Reactor/Multicast/.cvsignore4
-rw-r--r--ACE/examples/Reactor/Multicast/Log_Wrapper.cpp81
-rw-r--r--ACE/examples/Reactor/Multicast/Log_Wrapper.h68
-rw-r--r--ACE/examples/Reactor/Multicast/Makefile.am50
-rw-r--r--ACE/examples/Reactor/Multicast/README15
-rw-r--r--ACE/examples/Reactor/Multicast/Reactor_Multicast.mpc17
-rw-r--r--ACE/examples/Reactor/Multicast/client.cpp126
-rw-r--r--ACE/examples/Reactor/Multicast/server.cpp247
-rw-r--r--ACE/examples/Reactor/Ntalker/.cvsignore2
-rw-r--r--ACE/examples/Reactor/Ntalker/Makefile.am33
-rw-r--r--ACE/examples/Reactor/Ntalker/README17
-rw-r--r--ACE/examples/Reactor/Ntalker/Reactor_Ntalker.mpc6
-rw-r--r--ACE/examples/Reactor/Ntalker/ntalker.cpp231
-rw-r--r--ACE/examples/Reactor/Proactor/.cvsignore7
-rw-r--r--ACE/examples/Reactor/Proactor/Aio_Platform_Test_C.cpp137
-rw-r--r--ACE/examples/Reactor/Proactor/Makefile.am153
-rw-r--r--ACE/examples/Reactor/Proactor/Proactor.mpc59
-rw-r--r--ACE/examples/Reactor/Proactor/README75
-rw-r--r--ACE/examples/Reactor/Proactor/post_completions.cpp306
-rw-r--r--ACE/examples/Reactor/Proactor/simple_test_proactor.cpp269
-rw-r--r--ACE/examples/Reactor/Proactor/test_aiocb.cpp239
-rw-r--r--ACE/examples/Reactor/Proactor/test_aiocb_ace.cpp259
-rw-r--r--ACE/examples/Reactor/Proactor/test_aiosig.cpp294
-rw-r--r--ACE/examples/Reactor/Proactor/test_aiosig_ace.cpp358
-rw-r--r--ACE/examples/Reactor/Proactor/test_cancel.cpp246
-rw-r--r--ACE/examples/Reactor/Proactor/test_cancel.h47
-rw-r--r--ACE/examples/Reactor/Proactor/test_end_event_loop.cpp168
-rw-r--r--ACE/examples/Reactor/Proactor/test_multiple_loops.cpp140
-rw-r--r--ACE/examples/Reactor/Proactor/test_proactor.cpp679
-rw-r--r--ACE/examples/Reactor/Proactor/test_proactor.h56
-rw-r--r--ACE/examples/Reactor/Proactor/test_proactor2.cpp808
-rw-r--r--ACE/examples/Reactor/Proactor/test_proactor3.cpp864
-rw-r--r--ACE/examples/Reactor/Proactor/test_timeout.cpp130
-rw-r--r--ACE/examples/Reactor/Proactor/test_timeout_st.cpp99
-rw-r--r--ACE/examples/Reactor/Proactor/test_udp_proactor.cpp432
-rw-r--r--ACE/examples/Reactor/README20
-rw-r--r--ACE/examples/Reactor/TP_Reactor/AcceptHandler.cpp106
-rw-r--r--ACE/examples/Reactor/TP_Reactor/AcceptHandler.h75
-rw-r--r--ACE/examples/Reactor/TP_Reactor/Makefile.am53
-rw-r--r--ACE/examples/Reactor/TP_Reactor/README86
-rw-r--r--ACE/examples/Reactor/TP_Reactor/ReadHandler.cpp151
-rw-r--r--ACE/examples/Reactor/TP_Reactor/ReadHandler.h92
-rw-r--r--ACE/examples/Reactor/TP_Reactor/TP_Reactor.mpc18
-rw-r--r--ACE/examples/Reactor/TP_Reactor/client.cpp141
-rw-r--r--ACE/examples/Reactor/TP_Reactor/common.h29
-rw-r--r--ACE/examples/Reactor/TP_Reactor/run_test.pl41
-rw-r--r--ACE/examples/Reactor/TP_Reactor/server.cpp66
-rw-r--r--ACE/examples/Reactor/WFMO_Reactor/APC.cpp124
-rw-r--r--ACE/examples/Reactor/WFMO_Reactor/Abandoned.cpp141
-rw-r--r--ACE/examples/Reactor/WFMO_Reactor/Console_Input.cpp87
-rw-r--r--ACE/examples/Reactor/WFMO_Reactor/Directory_Changes.cpp128
-rw-r--r--ACE/examples/Reactor/WFMO_Reactor/Exceptions.cpp109
-rw-r--r--ACE/examples/Reactor/WFMO_Reactor/Handle_Close.cpp333
-rw-r--r--ACE/examples/Reactor/WFMO_Reactor/Makefile.am308
-rw-r--r--ACE/examples/Reactor/WFMO_Reactor/Multithreading.cpp262
-rw-r--r--ACE/examples/Reactor/WFMO_Reactor/Network_Events.cpp211
-rw-r--r--ACE/examples/Reactor/WFMO_Reactor/Prerun_State_Changes.cpp66
-rw-r--r--ACE/examples/Reactor/WFMO_Reactor/Registration.cpp169
-rw-r--r--ACE/examples/Reactor/WFMO_Reactor/Registry_Changes.cpp146
-rw-r--r--ACE/examples/Reactor/WFMO_Reactor/Removals.cpp114
-rw-r--r--ACE/examples/Reactor/WFMO_Reactor/Suspended_Removals.cpp173
-rw-r--r--ACE/examples/Reactor/WFMO_Reactor/Talker.cpp594
-rw-r--r--ACE/examples/Reactor/WFMO_Reactor/Timeouts.cpp83
-rw-r--r--ACE/examples/Reactor/WFMO_Reactor/WFMO_Reactor.mpc118
-rw-r--r--ACE/examples/Reactor/WFMO_Reactor/Window_Messages.cpp100
-rwxr-xr-xACE/examples/Reactor/WFMO_Reactor/run_test.pl68
-rw-r--r--ACE/examples/Registry/Makefile.am60
-rw-r--r--ACE/examples/Registry/Registry.mpc17
-rw-r--r--ACE/examples/Registry/test_registry_iterator.cpp146
-rw-r--r--ACE/examples/Registry/test_registry_update.cpp161
-rw-r--r--ACE/examples/Service_Configurator/IPC-tests/Makefile.am14
-rw-r--r--ACE/examples/Service_Configurator/IPC-tests/README125
-rw-r--r--ACE/examples/Service_Configurator/IPC-tests/client/.cvsignore10
-rw-r--r--ACE/examples/Service_Configurator/IPC-tests/client/Makefile.am180
-rw-r--r--ACE/examples/Service_Configurator/IPC-tests/client/Svc_Cfg_IPC_Client.mpc70
-rw-r--r--ACE/examples/Service_Configurator/IPC-tests/client/broadcast_client_test.cpp62
-rw-r--r--ACE/examples/Service_Configurator/IPC-tests/client/local_data22
-rw-r--r--ACE/examples/Service_Configurator/IPC-tests/client/local_dgram_client_test.cpp117
-rw-r--r--ACE/examples/Service_Configurator/IPC-tests/client/local_fifo_client_test.cpp101
-rw-r--r--ACE/examples/Service_Configurator/IPC-tests/client/local_pipe_client_test.cpp150
-rw-r--r--ACE/examples/Service_Configurator/IPC-tests/client/local_spipe_client_test.cpp106
-rw-r--r--ACE/examples/Service_Configurator/IPC-tests/client/local_stream_client_test.cpp113
-rw-r--r--ACE/examples/Service_Configurator/IPC-tests/client/remote_data22
-rw-r--r--ACE/examples/Service_Configurator/IPC-tests/client/remote_data122
-rw-r--r--ACE/examples/Service_Configurator/IPC-tests/client/remote_data222
-rw-r--r--ACE/examples/Service_Configurator/IPC-tests/client/remote_data322
-rw-r--r--ACE/examples/Service_Configurator/IPC-tests/client/remote_data422
-rw-r--r--ACE/examples/Service_Configurator/IPC-tests/client/remote_dgram_client_test.cpp92
-rw-r--r--ACE/examples/Service_Configurator/IPC-tests/client/remote_service_directory_test.cpp111
-rw-r--r--ACE/examples/Service_Configurator/IPC-tests/client/remote_stream_client_test.cpp134
-rw-r--r--ACE/examples/Service_Configurator/IPC-tests/client/remote_thr_stream_client_test.cpp122
-rw-r--r--ACE/examples/Service_Configurator/IPC-tests/server/.cvsignore1
-rw-r--r--ACE/examples/Service_Configurator/IPC-tests/server/Handle_Broadcast.cpp38
-rw-r--r--ACE/examples/Service_Configurator/IPC-tests/server/Handle_Broadcast.h50
-rw-r--r--ACE/examples/Service_Configurator/IPC-tests/server/Handle_Broadcast.i116
-rw-r--r--ACE/examples/Service_Configurator/IPC-tests/server/Handle_L_CODgram.cpp19
-rw-r--r--ACE/examples/Service_Configurator/IPC-tests/server/Handle_L_CODgram.h51
-rw-r--r--ACE/examples/Service_Configurator/IPC-tests/server/Handle_L_CODgram.i123
-rw-r--r--ACE/examples/Service_Configurator/IPC-tests/server/Handle_L_Dgram.cpp18
-rw-r--r--ACE/examples/Service_Configurator/IPC-tests/server/Handle_L_Dgram.h51
-rw-r--r--ACE/examples/Service_Configurator/IPC-tests/server/Handle_L_Dgram.i116
-rw-r--r--ACE/examples/Service_Configurator/IPC-tests/server/Handle_L_FIFO.cpp38
-rw-r--r--ACE/examples/Service_Configurator/IPC-tests/server/Handle_L_FIFO.h49
-rw-r--r--ACE/examples/Service_Configurator/IPC-tests/server/Handle_L_FIFO.i101
-rw-r--r--ACE/examples/Service_Configurator/IPC-tests/server/Handle_L_Pipe.cpp66
-rw-r--r--ACE/examples/Service_Configurator/IPC-tests/server/Handle_L_Pipe.h55
-rw-r--r--ACE/examples/Service_Configurator/IPC-tests/server/Handle_L_Pipe.i96
-rw-r--r--ACE/examples/Service_Configurator/IPC-tests/server/Handle_L_SPIPE.cpp18
-rw-r--r--ACE/examples/Service_Configurator/IPC-tests/server/Handle_L_SPIPE.h52
-rw-r--r--ACE/examples/Service_Configurator/IPC-tests/server/Handle_L_SPIPE.i131
-rw-r--r--ACE/examples/Service_Configurator/IPC-tests/server/Handle_L_Stream.cpp22
-rw-r--r--ACE/examples/Service_Configurator/IPC-tests/server/Handle_L_Stream.h53
-rw-r--r--ACE/examples/Service_Configurator/IPC-tests/server/Handle_L_Stream.i149
-rw-r--r--ACE/examples/Service_Configurator/IPC-tests/server/Handle_R_Dgram.cpp38
-rw-r--r--ACE/examples/Service_Configurator/IPC-tests/server/Handle_R_Dgram.h47
-rw-r--r--ACE/examples/Service_Configurator/IPC-tests/server/Handle_R_Dgram.i111
-rw-r--r--ACE/examples/Service_Configurator/IPC-tests/server/Handle_R_Stream.cpp42
-rw-r--r--ACE/examples/Service_Configurator/IPC-tests/server/Handle_R_Stream.h53
-rw-r--r--ACE/examples/Service_Configurator/IPC-tests/server/Handle_R_Stream.i153
-rw-r--r--ACE/examples/Service_Configurator/IPC-tests/server/Handle_Thr_Stream.cpp195
-rw-r--r--ACE/examples/Service_Configurator/IPC-tests/server/Handle_Thr_Stream.h73
-rw-r--r--ACE/examples/Service_Configurator/IPC-tests/server/Handle_Timeout.cpp36
-rw-r--r--ACE/examples/Service_Configurator/IPC-tests/server/Handle_Timeout.h45
-rw-r--r--ACE/examples/Service_Configurator/IPC-tests/server/Handle_Timeout.i86
-rw-r--r--ACE/examples/Service_Configurator/IPC-tests/server/Makefile.am106
-rw-r--r--ACE/examples/Service_Configurator/IPC-tests/server/Svc_Cfg_IPC_Server.mpc30
-rw-r--r--ACE/examples/Service_Configurator/IPC-tests/server/server_test.cpp54
-rw-r--r--ACE/examples/Service_Configurator/IPC-tests/server/svc.conf19
-rw-r--r--ACE/examples/Service_Configurator/Makefile.am14
-rw-r--r--ACE/examples/Service_Configurator/Misc/.cvsignore1
-rw-r--r--ACE/examples/Service_Configurator/Misc/Makefile.am50
-rw-r--r--ACE/examples/Service_Configurator/Misc/README23
-rw-r--r--ACE/examples/Service_Configurator/Misc/Service_Configurator_Misc.mpc18
-rw-r--r--ACE/examples/Service_Configurator/Misc/Timer_Service.cpp135
-rw-r--r--ACE/examples/Service_Configurator/Misc/Timer_Service.h71
-rw-r--r--ACE/examples/Service_Configurator/Misc/main.cpp80
-rw-r--r--ACE/examples/Service_Configurator/Misc/svc.conf18
-rw-r--r--ACE/examples/Service_Configurator/Misc/svc.conf28
-rw-r--r--ACE/examples/Shared_Malloc/.cvsignore4
-rw-r--r--ACE/examples/Shared_Malloc/Makefile.am106
-rw-r--r--ACE/examples/Shared_Malloc/Malloc.cpp69
-rw-r--r--ACE/examples/Shared_Malloc/Malloc.h33
-rw-r--r--ACE/examples/Shared_Malloc/Options.cpp201
-rw-r--r--ACE/examples/Shared_Malloc/Options.h86
-rw-r--r--ACE/examples/Shared_Malloc/Shared_Malloc.mpc37
-rw-r--r--ACE/examples/Shared_Malloc/test_malloc.cpp228
-rw-r--r--ACE/examples/Shared_Malloc/test_multiple_mallocs.cpp125
-rw-r--r--ACE/examples/Shared_Malloc/test_persistence.cpp350
-rw-r--r--ACE/examples/Shared_Malloc/test_position_independent_malloc.cpp190
-rw-r--r--ACE/examples/Shared_Malloc/test_position_independent_malloc.h28
-rw-r--r--ACE/examples/Shared_Memory/.cvsignore2
-rw-r--r--ACE/examples/Shared_Memory/Makefile.am56
-rw-r--r--ACE/examples/Shared_Memory/Shared_Memory.mpc17
-rw-r--r--ACE/examples/Shared_Memory/test_MM.cpp74
-rw-r--r--ACE/examples/Shared_Memory/test_SV.cpp64
-rw-r--r--ACE/examples/Smart_Pointers/.cvsignore2
-rw-r--r--ACE/examples/Smart_Pointers/Gadget.cpp16
-rw-r--r--ACE/examples/Smart_Pointers/Gadget.h51
-rw-r--r--ACE/examples/Smart_Pointers/Gadget_Factory.cpp18
-rw-r--r--ACE/examples/Smart_Pointers/Gadget_Factory.h32
-rw-r--r--ACE/examples/Smart_Pointers/Gadget_Impl.cpp47
-rw-r--r--ACE/examples/Smart_Pointers/Gadget_Impl.h51
-rw-r--r--ACE/examples/Smart_Pointers/Gadget_Part.cpp16
-rw-r--r--ACE/examples/Smart_Pointers/Gadget_Part.h45
-rw-r--r--ACE/examples/Smart_Pointers/Gadget_Part_Factory.cpp20
-rw-r--r--ACE/examples/Smart_Pointers/Gadget_Part_Factory.h35
-rw-r--r--ACE/examples/Smart_Pointers/Gadget_Part_Impl.cpp68
-rw-r--r--ACE/examples/Smart_Pointers/Gadget_Part_Impl.h64
-rw-r--r--ACE/examples/Smart_Pointers/Makefile.am70
-rw-r--r--ACE/examples/Smart_Pointers/README29
-rw-r--r--ACE/examples/Smart_Pointers/Smart_Pointers.mpc28
-rw-r--r--ACE/examples/Smart_Pointers/Widget.cpp16
-rw-r--r--ACE/examples/Smart_Pointers/Widget.h40
-rw-r--r--ACE/examples/Smart_Pointers/Widget_Factory.cpp18
-rw-r--r--ACE/examples/Smart_Pointers/Widget_Factory.h30
-rw-r--r--ACE/examples/Smart_Pointers/Widget_Impl.cpp52
-rw-r--r--ACE/examples/Smart_Pointers/Widget_Impl.h68
-rw-r--r--ACE/examples/Smart_Pointers/Widget_Part.cpp16
-rw-r--r--ACE/examples/Smart_Pointers/Widget_Part.h33
-rw-r--r--ACE/examples/Smart_Pointers/Widget_Part_Factory.cpp20
-rw-r--r--ACE/examples/Smart_Pointers/Widget_Part_Factory.h31
-rw-r--r--ACE/examples/Smart_Pointers/Widget_Part_Impl.cpp74
-rw-r--r--ACE/examples/Smart_Pointers/Widget_Part_Impl.h49
-rw-r--r--ACE/examples/Smart_Pointers/gadget_test.cpp52
-rw-r--r--ACE/examples/Smart_Pointers/widget_test.cpp51
-rw-r--r--ACE/examples/Synch/.cvsignore1
-rw-r--r--ACE/examples/Synch/Makefile.am38
-rw-r--r--ACE/examples/Synch/README21
-rw-r--r--ACE/examples/Synch/Synch.mpc7
-rw-r--r--ACE/examples/Synch/proc_sema.cpp98
-rw-r--r--ACE/examples/System_V_IPC/Makefile.am14
-rw-r--r--ACE/examples/System_V_IPC/README13
-rw-r--r--ACE/examples/System_V_IPC/SV_Message_Queues/.cvsignore4
-rw-r--r--ACE/examples/System_V_IPC/SV_Message_Queues/MQ_Client.cpp55
-rw-r--r--ACE/examples/System_V_IPC/SV_Message_Queues/MQ_Server.cpp81
-rw-r--r--ACE/examples/System_V_IPC/SV_Message_Queues/Makefile.am94
-rw-r--r--ACE/examples/System_V_IPC/SV_Message_Queues/SV_Message_Queues.mpc32
-rw-r--r--ACE/examples/System_V_IPC/SV_Message_Queues/TMQ_Client.cpp52
-rw-r--r--ACE/examples/System_V_IPC/SV_Message_Queues/TMQ_Server.cpp78
-rw-r--r--ACE/examples/System_V_IPC/SV_Message_Queues/test.h58
-rw-r--r--ACE/examples/System_V_IPC/SV_Semaphores/.cvsignore2
-rw-r--r--ACE/examples/System_V_IPC/SV_Semaphores/Makefile.am56
-rw-r--r--ACE/examples/System_V_IPC/SV_Semaphores/SV_Semaphores.mpc17
-rw-r--r--ACE/examples/System_V_IPC/SV_Semaphores/Semaphores_1.cpp94
-rw-r--r--ACE/examples/System_V_IPC/SV_Semaphores/Semaphores_2.cpp110
-rw-r--r--ACE/examples/System_V_IPC/SV_Shared_Memory/SV_Shared_Memory_Test.cpp78
-rw-r--r--ACE/examples/System_V_IPC/SV_Shared_Memory/SV_Shared_Memory_Test.h12
-rw-r--r--ACE/examples/TMCast/Makefile.am13
-rw-r--r--ACE/examples/TMCast/Member/.cvsignore1
-rw-r--r--ACE/examples/TMCast/Member/Makefile.am45
-rw-r--r--ACE/examples/TMCast/Member/Member.mpc7
-rw-r--r--ACE/examples/TMCast/Member/README36
-rw-r--r--ACE/examples/TMCast/Member/member.cpp93
-rw-r--r--ACE/examples/Threads/.cvsignore22
-rw-r--r--ACE/examples/Threads/Makefile.am408
-rw-r--r--ACE/examples/Threads/TSS_Data.h40
-rw-r--r--ACE/examples/Threads/TSS_Obj.h39
-rw-r--r--ACE/examples/Threads/TSS_Task.h43
-rw-r--r--ACE/examples/Threads/Threads.mpc139
-rw-r--r--ACE/examples/Threads/auto_event.cpp120
-rw-r--r--ACE/examples/Threads/barrier1.cpp83
-rw-r--r--ACE/examples/Threads/barrier2.cpp316
-rw-r--r--ACE/examples/Threads/cancel.cpp86
-rw-r--r--ACE/examples/Threads/future1.cpp404
-rw-r--r--ACE/examples/Threads/future2.cpp525
-rw-r--r--ACE/examples/Threads/manual_event.cpp114
-rw-r--r--ACE/examples/Threads/process_manager.cpp296
-rw-r--r--ACE/examples/Threads/process_mutex.cpp75
-rw-r--r--ACE/examples/Threads/process_semaphore.cpp63
-rw-r--r--ACE/examples/Threads/reader_writer.cpp188
-rw-r--r--ACE/examples/Threads/recursive_mutex.cpp113
-rw-r--r--ACE/examples/Threads/task_five.cpp177
-rw-r--r--ACE/examples/Threads/task_four.cpp307
-rw-r--r--ACE/examples/Threads/task_one.cpp102
-rw-r--r--ACE/examples/Threads/task_three.cpp268
-rw-r--r--ACE/examples/Threads/task_two.cpp147
-rw-r--r--ACE/examples/Threads/thread_manager.cpp108
-rw-r--r--ACE/examples/Threads/thread_pool.cpp268
-rw-r--r--ACE/examples/Threads/thread_specific.cpp228
-rw-r--r--ACE/examples/Threads/thread_specific.h53
-rw-r--r--ACE/examples/Threads/token.cpp78
-rw-r--r--ACE/examples/Threads/tss1.cpp157
-rw-r--r--ACE/examples/Threads/tss2.cpp190
-rw-r--r--ACE/examples/Threads/wfmo.cpp132
-rw-r--r--ACE/examples/Timer_Queue/.cvsignore3
-rw-r--r--ACE/examples/Timer_Queue/Async_Timer_Queue_Test.cpp299
-rw-r--r--ACE/examples/Timer_Queue/Async_Timer_Queue_Test.h119
-rw-r--r--ACE/examples/Timer_Queue/Driver.cpp164
-rw-r--r--ACE/examples/Timer_Queue/Driver.h137
-rw-r--r--ACE/examples/Timer_Queue/Makefile.am95
-rw-r--r--ACE/examples/Timer_Queue/README26
-rw-r--r--ACE/examples/Timer_Queue/Reactor_Timer_Queue_Test.cpp223
-rw-r--r--ACE/examples/Timer_Queue/Reactor_Timer_Queue_Test.h153
-rw-r--r--ACE/examples/Timer_Queue/Thread_Timer_Queue_Test.cpp270
-rw-r--r--ACE/examples/Timer_Queue/Thread_Timer_Queue_Test.h157
-rw-r--r--ACE/examples/Timer_Queue/Timer_Queue.mpc40
-rw-r--r--ACE/examples/Timer_Queue/main_async.cpp57
-rw-r--r--ACE/examples/Timer_Queue/main_reactor.cpp57
-rw-r--r--ACE/examples/Timer_Queue/main_thread.cpp58
-rw-r--r--ACE/examples/Web_Crawler/.cvsignore1
-rw-r--r--ACE/examples/Web_Crawler/Command_Processor.cpp128
-rw-r--r--ACE/examples/Web_Crawler/Command_Processor.h98
-rw-r--r--ACE/examples/Web_Crawler/HTTP_URL.cpp87
-rw-r--r--ACE/examples/Web_Crawler/HTTP_URL.h64
-rw-r--r--ACE/examples/Web_Crawler/Iterators.cpp163
-rw-r--r--ACE/examples/Web_Crawler/Iterators.h117
-rw-r--r--ACE/examples/Web_Crawler/Makefile.am60
-rw-r--r--ACE/examples/Web_Crawler/Mem_Map_Stream.cpp240
-rw-r--r--ACE/examples/Web_Crawler/Mem_Map_Stream.h190
-rw-r--r--ACE/examples/Web_Crawler/Options.cpp177
-rw-r--r--ACE/examples/Web_Crawler/Options.h124
-rw-r--r--ACE/examples/Web_Crawler/README25
-rw-r--r--ACE/examples/Web_Crawler/URL.cpp39
-rw-r--r--ACE/examples/Web_Crawler/URL.h82
-rw-r--r--ACE/examples/Web_Crawler/URL_Addr.cpp234
-rw-r--r--ACE/examples/Web_Crawler/URL_Addr.h111
-rw-r--r--ACE/examples/Web_Crawler/URL_Status.cpp40
-rw-r--r--ACE/examples/Web_Crawler/URL_Status.h61
-rw-r--r--ACE/examples/Web_Crawler/URL_Visitor.cpp543
-rw-r--r--ACE/examples/Web_Crawler/URL_Visitor.h436
-rw-r--r--ACE/examples/Web_Crawler/URL_Visitor_Factory.cpp53
-rw-r--r--ACE/examples/Web_Crawler/URL_Visitor_Factory.h74
-rw-r--r--ACE/examples/Web_Crawler/Web_Crawler.cpp95
-rw-r--r--ACE/examples/Web_Crawler/Web_Crawler.h62
-rw-r--r--ACE/examples/Web_Crawler/Web_Crawler.mpc7
-rw-r--r--ACE/examples/Web_Crawler/main.cpp51
-rw-r--r--ACE/examples/example_base.mpb8
-rw-r--r--ACE/examples/examples.mwc14
1002 files changed, 92336 insertions, 0 deletions
diff --git a/ACE/examples/APG/Active_Objects/.cvsignore b/ACE/examples/APG/Active_Objects/.cvsignore
new file mode 100644
index 00000000000..2af94b7dd8c
--- /dev/null
+++ b/ACE/examples/APG/Active_Objects/.cvsignore
@@ -0,0 +1,4 @@
+AO
+AO
+AO2
+AO2
diff --git a/ACE/examples/APG/Active_Objects/AO.cpp b/ACE/examples/APG/Active_Objects/AO.cpp
new file mode 100644
index 00000000000..b84a017d590
--- /dev/null
+++ b/ACE/examples/APG/Active_Objects/AO.cpp
@@ -0,0 +1,186 @@
+// $Id$
+
+#include "ace/config-lite.h"
+#if defined (ACE_HAS_THREADS)
+
+#include "ace/OS_NS_unistd.h"
+#include "ace/Activation_Queue.h"
+#include "ace/Method_Request.h"
+#include "ace/Task.h"
+#include "ace/Future.h"
+#include "ace/Auto_Ptr.h"
+// Listing 1 code/ch15
+class HA_ControllerAgent
+{
+ // Proxy to the HA_Controller that is on the network.
+public:
+ HA_ControllerAgent ()
+ {
+ ACE_TRACE
+ (ACE_TEXT ("HA_ControllerAgent::HA_ControllerAgent"));
+ status_result_ = 1;
+ }
+
+ int status_update (void)
+ {
+ ACE_TRACE (ACE_TEXT ("HA_ControllerAgent::status_update"));
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("Obtaining a status_update in %t ")
+ ACE_TEXT ("thread of control\n")));
+ // Simulate time to send message and get status.
+ ACE_OS::sleep (2);
+ return next_result_id ();
+ }
+
+private:
+ int next_result_id (void)
+ {
+ ACE_TRACE (ACE_TEXT ("HA_ControllerAgent::next_cmd_id"));
+ return status_result_++;
+ }
+
+ int status_result_;
+};
+// Listing 1
+// Listing 2 code/ch15
+class StatusUpdate : public ACE_Method_Request
+{
+public:
+ StatusUpdate (HA_ControllerAgent& controller,
+ ACE_Future<int>& returnVal)
+ : controller_(controller), returnVal_(returnVal)
+ {
+ ACE_TRACE (ACE_TEXT ("StatusUpdate::StatusUpdate"));
+ }
+
+ virtual int call (void)
+ {
+ ACE_TRACE (ACE_TEXT ("StatusUpdate::call"));
+
+ // status_update with the controller.
+ this->returnVal_.set (this->controller_.status_update ());
+ return 0;
+ }
+
+private:
+ HA_ControllerAgent& controller_;
+ ACE_Future<int> returnVal_;
+};
+// Listing 2
+// Listing 3 code/ch15
+class ExitMethod : public ACE_Method_Request
+{
+public:
+ virtual int call (void)
+ {
+ // Cause exit.
+ return -1;
+ }
+};
+// Listing 3
+// Listing 4 code/ch15
+class Scheduler : public ACE_Task_Base
+{
+public:
+ Scheduler ()
+ {
+ ACE_TRACE (ACE_TEXT ("Scheduler::Scheduler"));
+ this->activate ();
+ }
+
+ virtual int svc (void)
+ {
+ ACE_TRACE (ACE_TEXT ("Scheduler::svc"));
+
+ while (1)
+ {
+ // Dequeue the next method object
+ auto_ptr<ACE_Method_Request>
+ request (this->activation_queue_.dequeue ());
+
+ // Invoke the method request.
+ if (request->call () == -1)
+ break;
+ }
+
+ return 0;
+ }
+
+ int enqueue (ACE_Method_Request *request)
+ {
+ ACE_TRACE (ACE_TEXT ("Scheduler::enqueue"));
+ return this->activation_queue_.enqueue (request);
+ }
+
+private:
+ ACE_Activation_Queue activation_queue_;
+};
+// Listing 4
+// Listing 5 code/ch15
+class HA_ControllerAgentProxy
+{
+ // This acts as a Proxy to the controller impl object.
+public:
+ ACE_Future<int> status_update (void)
+ {
+ ACE_TRACE
+ (ACE_TEXT ("HA_ControllerAgentProxy::status_update"));
+ ACE_Future<int> result;
+
+ // Create and enqueue a method request on the scheduler.
+ this->scheduler_.enqueue
+ (new StatusUpdate (this->controller_, result));
+
+ // Return Future to the client.
+ return result;
+ }
+
+ void exit (void)
+ {
+ ACE_TRACE (ACE_TEXT ("HA_ControllerAgentProxy::exit"));
+ this->scheduler_.enqueue (new ExitMethod);
+ }
+
+private:
+ Scheduler scheduler_;
+ HA_ControllerAgent controller_;
+};
+// Listing 5
+// Listing 6 code/ch15
+int ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ HA_ControllerAgentProxy controller;
+ ACE_Future<int> results[10];
+
+ for (int i = 0 ; i < 10; i++)
+ results[i] = controller.status_update ();
+
+ ACE_OS::sleep (5); // Do other work.
+
+ // Get results...
+ for (int j = 0; j < 10; j++)
+ {
+ int result = 0;
+ results[j].get (result);
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("New status_update %d\n"), result));
+ }
+
+ // Cause the status_updater threads to exit.
+ controller.exit ();
+ ACE_Thread_Manager::instance ()->wait ();
+ return 0;
+}
+// Listing 6
+
+#else
+#include "ace/OS_main.h"
+#include "ace/OS_NS_stdio.h"
+
+int ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ ACE_OS::puts (ACE_TEXT ("This example requires threads."));
+ return 0;
+}
+
+#endif /* ACE_HAS_THREADS */
diff --git a/ACE/examples/APG/Active_Objects/AO2.cpp b/ACE/examples/APG/Active_Objects/AO2.cpp
new file mode 100644
index 00000000000..04553c8e1b8
--- /dev/null
+++ b/ACE/examples/APG/Active_Objects/AO2.cpp
@@ -0,0 +1,196 @@
+// $Id$
+
+#include "ace/config-lite.h"
+#if defined (ACE_HAS_THREADS)
+
+#include "ace/OS_NS_unistd.h"
+#include "ace/Activation_Queue.h"
+#include "ace/Method_Request.h"
+#include "ace/Task.h"
+#include "ace/Future.h"
+#include "ace/Auto_Ptr.h"
+
+class HA_ControllerAgent
+{
+ // Proxy to the HA_Controller that is on the network.
+public:
+ HA_ControllerAgent ()
+ {
+ ACE_TRACE
+ (ACE_TEXT ("HA_ControllerAgent::HA_ControllerAgent"));
+ status_result_ = 1;
+ }
+
+ int status_update (void)
+ {
+ ACE_TRACE (ACE_TEXT ("HA_ControllerAgent::status_update"));
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("Obtaining a status_update in %t ")
+ ACE_TEXT ("thread of control\n")));
+ // Simulate sending message to controller
+ // and getting status.
+ ACE_OS::sleep (2);
+ return next_result_id ();
+ }
+
+private:
+ int next_result_id (void)
+ {
+ ACE_TRACE (ACE_TEXT ("HA_ControllerAgent::next_cmd_id"));
+ return status_result_++;
+ }
+
+ int status_result_;
+};
+
+class StatusUpdate : public ACE_Method_Request
+{
+public:
+ StatusUpdate (HA_ControllerAgent& controller,
+ ACE_Future<int>& returnVal)
+ : controller_(controller), returnVal_(returnVal)
+ {
+ ACE_TRACE (ACE_TEXT ("StatusUpdate::StatusUpdate"));
+ }
+
+ virtual int call (void)
+ {
+ ACE_TRACE (ACE_TEXT ("StatusUpdate::call"));
+
+ // status_update with the controller.
+ this->returnVal_.set (this->controller_.status_update ());
+ return 0;
+ }
+
+private:
+ HA_ControllerAgent& controller_;
+ ACE_Future<int> returnVal_;
+};
+
+class ExitMethod : public ACE_Method_Request
+{
+public:
+ virtual int call (void)
+ {
+ // Cause exit.
+ return -1;
+ }
+};
+
+class Scheduler : public ACE_Task_Base
+{
+public:
+ Scheduler ()
+ {
+ ACE_TRACE (ACE_TEXT ("Scheduler::Scheduler"));
+ this->activate ();
+ }
+
+ virtual int svc (void)
+ {
+ ACE_TRACE (ACE_TEXT ("Scheduler::svc"));
+
+ while (1)
+ {
+ // Dequeue the next method object
+ auto_ptr<ACE_Method_Request>
+ request (this->activation_queue_.dequeue ());
+
+ // Invoke the method request.
+ if (request->call () == -1)
+ break;
+ }
+
+ return 0;
+ }
+
+ int enqueue (ACE_Method_Request *request)
+ {
+ ACE_TRACE (ACE_TEXT ("Scheduler::enqueue"));
+ return this->activation_queue_.enqueue (request);
+ }
+
+private:
+ ACE_Activation_Queue activation_queue_;
+};
+
+class HA_ControllerAgentProxy
+{
+ // This acts as a Proxy to the controller impl object.
+public:
+ ACE_Future<int> status_update (void)
+ {
+ ACE_TRACE
+ (ACE_TEXT ("HA_ControllerAgentProxy::status_update"));
+ ACE_Future<int> result;
+
+ // Create and enqueue a method request on the scheduler.
+ this->scheduler_.enqueue
+ (new StatusUpdate (this->controller_, result));
+
+ // Return Future to the client.
+ return result;
+ }
+
+ void exit (void)
+ {
+ ACE_TRACE (ACE_TEXT ("HA_ControllerAgentProxy::exit"));
+ this->scheduler_.enqueue (new ExitMethod);
+ }
+
+private:
+ Scheduler scheduler_;
+ HA_ControllerAgent controller_;
+};
+
+// Listing 1 code/ch15
+class CompletionCallBack : public ACE_Future_Observer<int>
+{
+public:
+ CompletionCallBack (HA_ControllerAgentProxy& proxy)
+ : proxy_(proxy)
+ { }
+
+ virtual void update (const ACE_Future<int>& future)
+ {
+ int result = 0;
+ ((ACE_Future<int>)future).get (result);
+ ACE_DEBUG ((LM_INFO,
+ ACE_TEXT ("(%t) New Status %d\n"), result));
+ if (result == 10)
+ this->proxy_.exit ();
+ }
+
+private:
+ HA_ControllerAgentProxy& proxy_;
+};
+// Listing 1
+// Listing 2 code/ch15
+int ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ HA_ControllerAgentProxy controller;
+ ACE_Future<int> results[10];
+ CompletionCallBack cb (controller);
+
+ for (int i = 0 ; i < 10; i++)
+ {
+ results[i] = controller.status_update ();
+ results[i].attach (&cb);
+ }
+
+ ACE_Thread_Manager::instance ()->wait ();
+ return 0;
+}
+// Listing 2
+
+#else
+#include "ace/OS_main.h"
+#include "ace/OS_NS_stdio.h"
+
+int ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ ACE_OS::puts (ACE_TEXT ("This example requires threads."));
+ return 0;
+}
+
+#endif /* ACE_HAS_THREADS */
diff --git a/ACE/examples/APG/Active_Objects/Makefile.am b/ACE/examples/APG/Active_Objects/Makefile.am
new file mode 100644
index 00000000000..4562743bc87
--- /dev/null
+++ b/ACE/examples/APG/Active_Objects/Makefile.am
@@ -0,0 +1,56 @@
+## Process this file with automake to create Makefile.in
+##
+## $Id$
+##
+## This file was generated by MPC. Any changes made directly to
+## this file will be lost the next time it is generated.
+##
+## MPC Command:
+## /acebuilds/ACE_wrappers-repository/bin/mwc.pl -include /acebuilds/MPC/config -include /acebuilds/MPC/templates -feature_file /acebuilds/ACE_wrappers-repository/local.features -noreldefs -type automake -exclude build,Kokyu
+
+ACE_BUILDDIR = $(top_builddir)
+ACE_ROOT = $(top_srcdir)
+
+noinst_PROGRAMS =
+
+## Makefile.AO.am
+
+if !BUILD_ACE_FOR_TAO
+noinst_PROGRAMS += AO
+
+AO_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+AO_SOURCES = \
+ AO.cpp
+
+AO_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+endif !BUILD_ACE_FOR_TAO
+
+## Makefile.AO2.am
+
+if !BUILD_ACE_FOR_TAO
+noinst_PROGRAMS += AO2
+
+AO2_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+AO2_SOURCES = \
+ AO2.cpp
+
+AO2_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+endif !BUILD_ACE_FOR_TAO
+
+## Clean up template repositories, etc.
+clean-local:
+ -rm -f *~ *.bak *.rpo *.sym lib*.*_pure_* core core.*
+ -rm -f gcctemp.c gcctemp so_locations *.ics
+ -rm -rf cxx_repository ptrepository ti_files
+ -rm -rf templateregistry ir.out
+ -rm -rf ptrepository SunWS_cache Templates.DB
diff --git a/ACE/examples/APG/Active_Objects/active_objects.mpc b/ACE/examples/APG/Active_Objects/active_objects.mpc
new file mode 100644
index 00000000000..44fe88bfd30
--- /dev/null
+++ b/ACE/examples/APG/Active_Objects/active_objects.mpc
@@ -0,0 +1,18 @@
+// -*- MPC -*-
+// $Id$
+
+project(AO) : aceexe {
+ avoids += ace_for_tao
+ exename = AO
+ Source_Files {
+ AO.cpp
+ }
+}
+
+project(AO2) : aceexe {
+ avoids += ace_for_tao
+ exename = AO2
+ Source_Files {
+ AO2.cpp
+ }
+}
diff --git a/ACE/examples/APG/Config/.cvsignore b/ACE/examples/APG/Config/.cvsignore
new file mode 100644
index 00000000000..b9f807ab7a6
--- /dev/null
+++ b/ACE/examples/APG/Config/.cvsignore
@@ -0,0 +1,6 @@
+ARGV_Example
+ARGV_Example
+Get_Opt
+Get_Opt
+Get_Opt_Long
+Get_Opt_Long
diff --git a/ACE/examples/APG/Config/ARGV_Example.cpp b/ACE/examples/APG/Config/ARGV_Example.cpp
new file mode 100644
index 00000000000..92fb25cd30d
--- /dev/null
+++ b/ACE/examples/APG/Config/ARGV_Example.cpp
@@ -0,0 +1,62 @@
+/**
+ * $Id$
+ *
+ * ACE_ARGV examples not in a larger program. Sample code from The ACE
+ * Programmer's Guide, Copyright 2003 Addison-Wesley. All Rights Reserved.
+ */
+
+#include "ace/os_include/os_netdb.h"
+#include "ace/OS_NS_string.h"
+#include "ace/Log_Msg.h"
+
+// Listing 1 code/ch04
+#include "ace/ARGV.h"
+#include "ace/Get_Opt.h"
+
+int ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ static const ACE_TCHAR options[] = ACE_TEXT (":f:h:");
+ static const ACE_TCHAR cmdline[] =
+ ACE_TEXT ("-f /home/managed.cfg -h $HOSTNAME");
+ ACE_ARGV cmdline_args (cmdline);
+ ACE_Get_Opt cmd_opts (cmdline_args.argc (),
+ cmdline_args.argv (),
+ options,
+ 0); // Don't skip any args
+
+// Listing 1
+
+ int option;
+ ACE_TCHAR config_file[MAXPATHLEN];
+ ACE_TCHAR hostname[MAXHOSTNAMELEN];
+ ACE_OS_String::strcpy (config_file, ACE_TEXT ("HAStatus.conf"));
+ ACE_OS_String::strcpy (hostname, ACE_TEXT ("not set"));
+ while ((option = cmd_opts ()) != EOF)
+ switch (option) {
+ case 'f':
+ ACE_OS_String::strncpy (config_file,
+ cmd_opts.opt_arg (),
+ MAXPATHLEN);
+ break;
+
+ case 'h':
+ ACE_OS_String::strncpy (hostname,
+ cmd_opts.opt_arg (),
+ MAXHOSTNAMELEN);
+ break;
+
+ case ':':
+ ACE_ERROR_RETURN
+ ((LM_ERROR, ACE_TEXT ("-%c requires an argument\n"),
+ cmd_opts.opt_opt ()), -1);
+
+
+ default:
+ ACE_ERROR_RETURN
+ ((LM_ERROR, ACE_TEXT ("Parse error.\n")), -1);
+ }
+
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Config file: %s\n"), config_file));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Hostname: %s\n"), hostname));
+ return 0;
+}
diff --git a/ACE/examples/APG/Config/Get_Opt.cpp b/ACE/examples/APG/Config/Get_Opt.cpp
new file mode 100644
index 00000000000..604dc38326e
--- /dev/null
+++ b/ACE/examples/APG/Config/Get_Opt.cpp
@@ -0,0 +1,59 @@
+/**
+ * $Id$
+ *
+ * ACE_Get_Opt examples not in a larger program. Sample code from The ACE
+ * Programmer's Guide, Copyright 2003 Addison-Wesley. All Rights Reserved.
+ */
+
+#include "ace/OS_NS_string.h"
+#include "ace/Get_Opt.h"
+#include "ace/Log_Msg.h"
+
+int
+ACE_TMAIN (int argc, ACE_TCHAR *argv[])
+{
+
+ // Example for a long option without a corresponding short option.
+ // Just put some context here so the following compiles and runs.
+ static const ACE_TCHAR options[] = ACE_TEXT (":f:");
+ ACE_Get_Opt cmd_opts (argc, argv, options);
+
+ // Listing 1 code/ch04
+ cmd_opts.long_option (ACE_TEXT ("cool_option"));
+ cmd_opts.long_option (ACE_TEXT ("the_answer"), 42);
+ // Listing 1
+
+ int option;
+ ACE_TCHAR config_file[MAXPATHLEN];
+ ACE_OS_String::strcpy (config_file, ACE_TEXT ("HAStatus.conf"));
+ while ((option = cmd_opts ()) != EOF)
+ switch (option) {
+ case 'f':
+ ACE_OS_String::strncpy (config_file,
+ cmd_opts.opt_arg (),
+ MAXPATHLEN);
+ break;
+
+ // Listing 2 code/ch04
+ case 0:
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Yes, very cool.\n")));
+ break;
+
+ case 42:
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("the_answer is 42\n")));
+ break;
+ // Listing 2
+
+ case ':':
+ ACE_ERROR_RETURN
+ ((LM_ERROR, ACE_TEXT ("-%c requires an argument\n"),
+ cmd_opts.opt_opt ()), -1);
+
+
+ default:
+ ACE_ERROR_RETURN
+ ((LM_ERROR, ACE_TEXT ("Parse error.\n")), -1);
+ }
+
+ return 0;
+}
diff --git a/ACE/examples/APG/Config/Get_Opt_Long.cpp b/ACE/examples/APG/Config/Get_Opt_Long.cpp
new file mode 100644
index 00000000000..66baed05cdb
--- /dev/null
+++ b/ACE/examples/APG/Config/Get_Opt_Long.cpp
@@ -0,0 +1,48 @@
+/**
+ * $Id$
+ *
+ * ACE_Get_Opt long_only examples. Sample code from The ACE
+ * Programmer's Guide, Copyright 2003 Addison-Wesley. All Rights Reserved.
+ */
+
+#include "ace/OS_NS_string.h"
+#include "ace/Get_Opt.h"
+#include "ace/Log_Msg.h"
+
+int
+ACE_TMAIN (int argc, ACE_TCHAR *argv[])
+{
+
+ static const ACE_TCHAR options[] = ACE_TEXT (":f:");
+ ACE_Get_Opt cmd_opts
+ (argc, argv, options, 1, 0, ACE_Get_Opt::PERMUTE_ARGS, 1);
+ if (cmd_opts.long_option
+ (ACE_TEXT ("config"), 'f', ACE_Get_Opt::ARG_REQUIRED) == -1)
+ return -1;
+
+ int option;
+ ACE_TCHAR config_file[MAXPATHLEN];
+ ACE_OS_String::strcpy (config_file, ACE_TEXT ("HAStatus.conf"));
+ while ((option = cmd_opts ()) != EOF)
+ switch (option) {
+ case 'f':
+ ACE_OS_String::strncpy (config_file,
+ cmd_opts.opt_arg (),
+ MAXPATHLEN);
+ break;
+
+ case ':':
+ ACE_ERROR_RETURN
+ ((LM_ERROR, ACE_TEXT ("-%c requires an argument\n"),
+ cmd_opts.opt_opt ()), -1);
+
+
+ default:
+ ACE_ERROR_RETURN
+ ((LM_ERROR, ACE_TEXT ("Parse error.\n")), -1);
+ }
+
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Config file is %s\n"), config_file));
+
+ return 0;
+}
diff --git a/ACE/examples/APG/Config/HASTATUS_export.h b/ACE/examples/APG/Config/HASTATUS_export.h
new file mode 100644
index 00000000000..09fe1797f80
--- /dev/null
+++ b/ACE/examples/APG/Config/HASTATUS_export.h
@@ -0,0 +1,54 @@
+
+// -*- C++ -*-
+// $Id$
+// Definition for Win32 Export directives.
+// This file is generated automatically by generate_export_file.pl HASTATUS
+// ------------------------------
+#ifndef HASTATUS_EXPORT_H
+#define HASTATUS_EXPORT_H
+
+#include "ace/config-all.h"
+
+#if defined (ACE_AS_STATIC_LIBS) && !defined (HASTATUS_HAS_DLL)
+# define HASTATUS_HAS_DLL 0
+#endif /* ACE_AS_STATIC_LIBS && ! HASTATUS_HAS_DLL */
+
+#if !defined (HASTATUS_HAS_DLL)
+# define HASTATUS_HAS_DLL 1
+#endif /* ! HASTATUS_HAS_DLL */
+
+#if defined (HASTATUS_HAS_DLL) && (HASTATUS_HAS_DLL == 1)
+# if defined (HASTATUS_BUILD_DLL)
+# define HASTATUS_Export ACE_Proper_Export_Flag
+# define HASTATUS_SINGLETON_DECLARATION(T) ACE_EXPORT_SINGLETON_DECLARATION (T)
+# define HASTATUS_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) ACE_EXPORT_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK)
+# else /* HASTATUS_BUILD_DLL */
+# define HASTATUS_Export ACE_Proper_Import_Flag
+# define HASTATUS_SINGLETON_DECLARATION(T) ACE_IMPORT_SINGLETON_DECLARATION (T)
+# define HASTATUS_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) ACE_IMPORT_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK)
+# endif /* HASTATUS_BUILD_DLL */
+#else /* HASTATUS_HAS_DLL == 1 */
+# define HASTATUS_Export
+# define HASTATUS_SINGLETON_DECLARATION(T)
+# define HASTATUS_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK)
+#endif /* HASTATUS_HAS_DLL == 1 */
+
+// Set HASTATUS_NTRACE = 0 to turn on library specific tracing even if
+// tracing is turned off for ACE.
+#if !defined (HASTATUS_NTRACE)
+# if (ACE_NTRACE == 1)
+# define HASTATUS_NTRACE 1
+# else /* (ACE_NTRACE == 1) */
+# define HASTATUS_NTRACE 0
+# endif /* (ACE_NTRACE == 1) */
+#endif /* !HASTATUS_NTRACE */
+
+#if (HASTATUS_NTRACE == 1)
+# define HASTATUS_TRACE(X)
+#else /* (HASTATUS_NTRACE == 1) */
+# define HASTATUS_TRACE(X) ACE_TRACE_IMPL(X)
+#endif /* (HASTATUS_NTRACE == 1) */
+
+#endif /* HASTATUS_EXPORT_H */
+
+// End of auto generated file.
diff --git a/ACE/examples/APG/Config/HA_Status.cpp b/ACE/examples/APG/Config/HA_Status.cpp
new file mode 100644
index 00000000000..1bad687be80
--- /dev/null
+++ b/ACE/examples/APG/Config/HA_Status.cpp
@@ -0,0 +1,98 @@
+/**
+ * $Id$
+ *
+ * Home Automation Status server. Sample code from The ACE Programmer's Guide,
+ * Copyright 2003 Addison-Wesley. All Rights Reserved.
+ */
+
+#include "ace/OS_NS_string.h"
+#include "ace/Configuration.h"
+#include "ace/Configuration_Import_Export.h"
+#include "ace/Get_Opt.h"
+#include "ace/Log_Msg.h"
+#include "ace/INET_Addr.h"
+#include "ace/Service_Object.h"
+
+class HA_Status : public ACE_Service_Object
+{
+public:
+ virtual int init (int argc, ACE_TCHAR *argv[]);
+
+private:
+ ACE_INET_Addr listen_addr_;
+};
+
+
+int
+HA_Status::init (int argc, ACE_TCHAR *argv[])
+{
+
+ // Do ACE_Get_Opt and get conf file name, read out the sections
+ // and print the names.
+
+ // Listing 1 code/ch04
+ static const ACE_TCHAR options[] = ACE_TEXT (":f:");
+ ACE_Get_Opt cmd_opts (argc, argv, options);
+ if (cmd_opts.long_option
+ (ACE_TEXT ("config"), 'f', ACE_Get_Opt::ARG_REQUIRED) == -1)
+ return -1;
+ int option;
+ ACE_TCHAR config_file[MAXPATHLEN];
+ ACE_OS::strcpy (config_file, ACE_TEXT ("HAStatus.conf"));
+ while ((option = cmd_opts ()) != EOF)
+ switch (option) {
+ case 'f':
+ ACE_OS::strncpy (config_file,
+ cmd_opts.opt_arg (),
+ MAXPATHLEN);
+ break;
+ case ':':
+ ACE_ERROR_RETURN
+ ((LM_ERROR, ACE_TEXT ("-%c requires an argument\n"),
+ cmd_opts.opt_opt ()), -1);
+ default:
+ ACE_ERROR_RETURN
+ ((LM_ERROR, ACE_TEXT ("Parse error.\n")), -1);
+ }
+ // Listing 1
+
+ // Listing 2 code/ch04
+ ACE_Configuration_Heap config;
+ if (config.open () == -1)
+ ACE_ERROR_RETURN
+ ((LM_ERROR, ACE_TEXT ("%p\n"), ACE_TEXT ("config")), -1);
+ ACE_Registry_ImpExp config_importer (config);
+ if (config_importer.import_config (config_file) == -1)
+ ACE_ERROR_RETURN
+ ((LM_ERROR, ACE_TEXT ("%p\n"), config_file), -1);
+
+ ACE_Configuration_Section_Key status_section;
+ if (config.open_section (config.root_section (),
+ ACE_TEXT ("HAStatus"),
+ 0,
+ status_section) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("%p\n"),
+ ACE_TEXT ("Can't open HAStatus section")),
+ -1);
+
+ u_int status_port;
+ if (config.get_integer_value (status_section,
+ ACE_TEXT ("ListenPort"),
+ status_port) == -1)
+ ACE_ERROR_RETURN
+ ((LM_ERROR,
+ ACE_TEXT ("HAStatus ListenPort does not exist\n")),
+ -1);
+ this->listen_addr_.set (static_cast<u_short> (status_port));
+ // Listing 2
+
+ return 0;
+}
+
+int
+ACE_TMAIN (int argc, ACE_TCHAR *argv[])
+{
+ HA_Status status;
+ status.init (argc, argv);
+ return 0;
+}
diff --git a/ACE/examples/APG/Config/Makefile.am b/ACE/examples/APG/Config/Makefile.am
new file mode 100644
index 00000000000..5320bfdf85c
--- /dev/null
+++ b/ACE/examples/APG/Config/Makefile.am
@@ -0,0 +1,81 @@
+## Process this file with automake to create Makefile.in
+##
+## $Id$
+##
+## This file was generated by MPC. Any changes made directly to
+## this file will be lost the next time it is generated.
+##
+## MPC Command:
+## /acebuilds/ACE_wrappers-repository/bin/mwc.pl -include /acebuilds/MPC/config -include /acebuilds/MPC/templates -feature_file /acebuilds/ACE_wrappers-repository/local.features -noreldefs -type automake -exclude build,Kokyu
+
+ACE_BUILDDIR = $(top_builddir)
+ACE_ROOT = $(top_srcdir)
+
+
+## Makefile.ARGV_Example.am
+noinst_PROGRAMS = ARGV_Example
+
+ARGV_Example_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+ARGV_Example_SOURCES = \
+ ARGV_Example.cpp \
+ HASTATUS_export.h
+
+ARGV_Example_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Makefile.Config_HA_Status.am
+
+if !BUILD_ACE_FOR_TAO
+noinst_PROGRAMS += HA_Status
+
+HA_Status_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+HA_Status_SOURCES = \
+ HA_Status.cpp \
+ HASTATUS_export.h
+
+HA_Status_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+endif !BUILD_ACE_FOR_TAO
+
+## Makefile.Get_Opt.am
+noinst_PROGRAMS += Get_Opt
+
+Get_Opt_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+Get_Opt_SOURCES = \
+ Get_Opt.cpp \
+ HASTATUS_export.h
+
+Get_Opt_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Makefile.Get_Opt_Long.am
+noinst_PROGRAMS += Get_Opt_Long
+
+Get_Opt_Long_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+Get_Opt_Long_SOURCES = \
+ Get_Opt_Long.cpp \
+ HASTATUS_export.h
+
+Get_Opt_Long_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Clean up template repositories, etc.
+clean-local:
+ -rm -f *~ *.bak *.rpo *.sym lib*.*_pure_* core core.*
+ -rm -f gcctemp.c gcctemp so_locations *.ics
+ -rm -rf cxx_repository ptrepository ti_files
+ -rm -rf templateregistry ir.out
+ -rm -rf ptrepository SunWS_cache Templates.DB
diff --git a/ACE/examples/APG/Config/config.mpc b/ACE/examples/APG/Config/config.mpc
new file mode 100644
index 00000000000..5b705d144bc
--- /dev/null
+++ b/ACE/examples/APG/Config/config.mpc
@@ -0,0 +1,31 @@
+// -*- MPC -*-
+// $Id$
+
+project(*HA Status) : aceexe {
+ avoids += ace_for_tao
+ exename = HA_Status
+ Source_Files {
+ HA_Status.cpp
+ }
+}
+
+project(Get Opt) : aceexe {
+ exename = Get_Opt
+ Source_Files {
+ Get_Opt.cpp
+ }
+}
+
+project(Get Opt Long) : aceexe {
+ exename = Get_Opt_Long
+ Source_Files {
+ Get_Opt_Long.cpp
+ }
+}
+
+project(ARGV Example) : aceexe {
+ exename = ARGV_Example
+ Source_Files {
+ ARGV_Example.cpp
+ }
+}
diff --git a/ACE/examples/APG/Containers/.cvsignore b/ACE/examples/APG/Containers/.cvsignore
new file mode 100644
index 00000000000..20d09b55a72
--- /dev/null
+++ b/ACE/examples/APG/Containers/.cvsignore
@@ -0,0 +1,24 @@
+Allocator
+Allocator
+Array
+Array
+DLList
+DLList
+Hash_Map
+Hash_Map
+Hash_Map_Hash
+Hash_Map_Hash
+Map_Manager
+Map_Manager
+Map_Manager_Specialization
+Map_Manager_Specialization
+Queues
+Queues
+RB_Tree
+RB_Tree
+RB_Tree_Functors
+RB_Tree_Functors
+Sets
+Sets
+Stacks
+Stacks
diff --git a/ACE/examples/APG/Containers/Allocator.cpp b/ACE/examples/APG/Containers/Allocator.cpp
new file mode 100644
index 00000000000..847235a3061
--- /dev/null
+++ b/ACE/examples/APG/Containers/Allocator.cpp
@@ -0,0 +1,93 @@
+// $Id$
+
+#include "ace/Containers.h"
+#include "ace/Malloc_T.h"
+#include "ace/Synch.h" // Needed for the lock.
+#include "DataElement.h"
+
+class StackExample
+{
+public:
+ // Illustrate all the differnet
+ // types of stacks provided by ACE.
+ int run (void);
+
+private:
+ // Illustrate the use of an unbounded stack.
+ int runUnboundedStack (ACE_Allocator* allocator);
+};
+
+// Listing 1 code/ch05
+int StackExample::run (void)
+{
+ ACE_TRACE (ACE_TEXT ("StackUser::run"));
+
+ ACE_Allocator *allocator = 0;
+ size_t block_size = sizeof(ACE_Node<DataElement>);
+ ACE_NEW_RETURN
+ (allocator,
+ ACE_Dynamic_Cached_Allocator<ACE_Null_Mutex>
+ (100 + 1, block_size),
+ -1);
+
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\n# of live objects %d\n"),
+ DataElement::numOfActiveObjects ()));
+
+ ACE_ASSERT (this->runUnboundedStack (allocator) != -1);
+
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\n# of live objects %d\n"),
+ DataElement::numOfActiveObjects ()));
+
+ delete allocator;
+ return 0;
+}
+// Listing 1
+// Listing 2 code/ch05
+int StackExample::runUnboundedStack (ACE_Allocator* allocator)
+{
+ ACE_TRACE (ACE_TEXT ("StackExample::runUnboundedStack"));
+
+ // Pass in an allocator during construction.
+ ACE_Unbounded_Stack<DataElement> ustack (allocator);
+
+ for (int m = 0; m < 100; m++)
+ {
+ DataElement elem (m);
+ int result = ustack.push (elem);
+ if (result == -1)
+ ACE_ERROR_RETURN
+ ((LM_ERROR, ACE_TEXT ("%p\n"),
+ ACE_TEXT ("Push Next Element")),
+ -1);
+ }
+
+ void* furtherMemory = 0;
+ furtherMemory = allocator->malloc
+ (sizeof(ACE_Node<DataElement>));
+ ACE_ASSERT (furtherMemory == 0);
+
+ // No memory left..
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("%p\n"),
+ ACE_TEXT ("No memory..")));
+
+ // Free up some memory in the allocator.
+ DataElement e;
+ for (int n = 0; n < 10; n++)
+ {
+ ustack.pop (e);
+ }
+
+ furtherMemory =
+ allocator->malloc (sizeof (ACE_Node<DataElement>));
+ ACE_ASSERT (furtherMemory != 0);
+
+ return 0;
+}
+// Listing 2
+
+int ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ StackExample se;
+ return se.run ();
+}
+
diff --git a/ACE/examples/APG/Containers/Array.cpp b/ACE/examples/APG/Containers/Array.cpp
new file mode 100644
index 00000000000..1ffb19f22e9
--- /dev/null
+++ b/ACE/examples/APG/Containers/Array.cpp
@@ -0,0 +1,41 @@
+// $Id$
+
+#include "ace/OS_Memory.h"
+#include "ace/Log_Msg.h"
+// Listing 1 code/ch05
+#include "ace/Containers.h"
+#include "DataElement.h"
+
+int ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ ACE_Array<DataElement*> arr (10);
+ DataElement *elem = 0;
+ // Allocate and insert elements.
+ for (int i = 0; i < 10; i++)
+ {
+ ACE_NEW_RETURN (elem, DataElement (i), -1);
+ arr[i] = elem;
+ }
+
+ // Checked access.
+ ACE_ASSERT (arr.set (elem, 11) == -1);
+ ACE_ASSERT (arr.get (elem, 11) == -1);
+
+ // Make a copy and compare to the original.
+ ACE_Array<DataElement*> copy = arr;
+ ACE_ASSERT (copy == arr);
+
+ ACE_Array<DataElement*>::ITERATOR iter (arr);
+ while (!iter.done ())
+ {
+ DataElement** data;
+ iter.next (data);
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("%d\n"), (*data)->getData ()));
+ delete (*data);
+ iter.advance ();
+ }
+ return 0;
+}
+// Listing 1
+
diff --git a/ACE/examples/APG/Containers/DLList.cpp b/ACE/examples/APG/Containers/DLList.cpp
new file mode 100644
index 00000000000..8c93e5b4039
--- /dev/null
+++ b/ACE/examples/APG/Containers/DLList.cpp
@@ -0,0 +1,116 @@
+// $Id$
+
+#include "ace/OS_Memory.h"
+#include "ace/Log_Msg.h"
+
+// Listing 1 code/ch05
+#include "ace/Containers.h"
+#include "DataElement.h"
+
+// Create a new type of list that can store only DataElements.
+typedef ACE_DLList<DataElement> MyList;
+// Listing 1
+
+// Listing 2 code/ch05
+class ListTest
+{
+public:
+ int run (void);
+ void displayList (MyList & list); // Display all elements.
+ void destroyList (MyList& list); // Destroy all elements.
+};
+// Listing 2
+// Listing 3 code/ch05
+int
+ListTest::run (void)
+{
+ ACE_TRACE (ACE_TEXT ("ListTest::run"));
+
+ // Create a list and insert 100 elements.
+ MyList list1;
+
+ for (int i = 0; i < 100; i++)
+ {
+ DataElement *element;
+ ACE_NEW_RETURN (element, DataElement (i), -1);
+ list1.insert_tail (element);
+ }
+
+ // Iterate through and display to output.
+ this->displayList (list1);
+
+ // Create a copy of list1.
+ MyList list2;
+ list2 = list1;
+
+ // Iterate over the copy and display it to output.
+ this->displayList(list2);
+
+ // Get rid of the copy list and all its elements.
+ // Since both lists had the *same* elements
+ // this will cause list1 to contain pointers that
+ // point to data elements that have already been destroyed!
+ this->destroyList (list2);
+
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("# of live objects: %d\n"),
+ DataElement::numOfActiveObjects()));
+
+ // The lists themselves are destroyed here. Note that the
+ // list destructor will destroy copies of whatever data the
+ // list contained. Since in this case the list contained
+ // copies of pointers to the data elements these are the
+ // only thing that gets destroyed here.
+ return 0;
+}
+// Listing 3
+// Listing 4 code/ch05
+void
+ListTest::destroyList (MyList& list)
+{
+ ACE_TRACE (ACE_TEXT ("ListTest::destroyList"));
+
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Destroying data elements\n")));
+
+ // Iterate through and delete all the data elements on the list.
+ for (ACE_DLList_Iterator<DataElement> iter (list);
+ !iter.done ();
+ iter++)
+ {
+ DataElement *de = iter.next ();
+ delete de;
+ }
+}
+// Listing 4
+// Listing 5 code/ch05
+void
+ListTest::displayList (MyList& list)
+{
+ ACE_TRACE (ACE_TEXT ("ListTest::displayList"));
+
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Forward iteration\n")));
+ ACE_DLList_Iterator<DataElement> iter (list);
+ while (!iter.done ())
+ {
+ ACE_DEBUG
+ ((LM_DEBUG, ACE_TEXT ("%d:"), iter.next()->getData()));
+ iter++;
+ }
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\n")));
+
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Reverse Iteration \n")));
+ ACE_DLList_Reverse_Iterator<DataElement> riter (list);
+ while (!riter.done ())
+ {
+ ACE_DEBUG
+ ((LM_DEBUG, ACE_TEXT ("%d:"), riter.next()->getData()));
+ riter++;
+ }
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\n")));
+}
+// Listing 5
+int ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ ListTest test;
+ return test.run ();
+}
+
diff --git a/ACE/examples/APG/Containers/DataElement.h b/ACE/examples/APG/Containers/DataElement.h
new file mode 100644
index 00000000000..cd09d86fa87
--- /dev/null
+++ b/ACE/examples/APG/Containers/DataElement.h
@@ -0,0 +1,52 @@
+/* -*- C++ -*- */
+// $Id$
+
+#if !defined(DATAELEMENT_H)
+#define DATAELEMENT_H
+
+class DataElementEx;
+
+// Listing 1 code/ch05
+// A simple data element class.
+class DataElement
+{
+ friend class DataElementEx;
+
+public:
+ DataElement () : data_ (0) { count_++; }
+
+ DataElement (int data) : data_(data) { count_++; }
+
+ DataElement (const DataElement& e)
+ {
+ data_ = e.getData ();
+ count_++;
+ }
+
+ DataElement & operator= (const DataElement& e)
+ {
+ data_ = e.getData ();
+ return *this;
+ }
+
+ bool operator== (const DataElement& e)
+ { return this->data_ == e.data_; }
+
+ ~DataElement () { count_--; }
+
+ int getData (void) const { return data_; }
+
+ void setData (int val) { data_ = val; }
+
+ static int numOfActiveObjects (void) { return count_; }
+
+ private:
+ int data_;
+ static int count_;
+};
+// Listing 1
+
+int DataElement::count_ = 0;
+
+#endif /*DATAELEMENT_H*/
+
diff --git a/ACE/examples/APG/Containers/Hash_Map.cpp b/ACE/examples/APG/Containers/Hash_Map.cpp
new file mode 100644
index 00000000000..1b2d4ee4634
--- /dev/null
+++ b/ACE/examples/APG/Containers/Hash_Map.cpp
@@ -0,0 +1,118 @@
+// $Id$
+
+#include "ace/Hash_Map_Manager.h"
+#include "ace/Synch.h" // needed for the lock
+#include "ace/Functor.h"
+#include "DataElement.h"
+
+// Listing 1 code/ch05
+// Little helper class.
+template<class EXT_ID, class INT_ID>
+class Hash_Map :
+ public ACE_Hash_Map_Manager_Ex<EXT_ID, INT_ID,
+ ACE_Hash<EXT_ID>, ACE_Equal_To<EXT_ID>, ACE_Null_Mutex>
+{};
+// Listing 1
+
+class Hash_Map_Example
+{
+public:
+ // Constructor
+ Hash_Map_Example ();
+
+ // Illustrate the hash map.
+ int run (void);
+
+ // Use the forward iterator.
+ void iterate_forward (void);
+
+ // Use the reverse iterator.
+ void iterate_reverse (void);
+
+ // Remove all the elements from the map.
+ void remove_all (void);
+
+private:
+ Hash_Map<int, DataElement> map_;
+};
+
+// Listing 2 code/ch05
+Hash_Map_Example::Hash_Map_Example()
+{
+ ACE_TRACE (ACE_TEXT ("Hash_Map_Example::Hash_Map_Example"));
+
+ map_.open (100);
+}
+// Listing 2
+
+int Hash_Map_Example::run (void)
+{
+ ACE_TRACE (ACE_TEXT ("Hash_Map_Example::run"));
+
+ for (int i = 0; i < 100; i++)
+ {
+ map_.bind (i, DataElement(i));
+ }
+
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Map has \n")));
+ for (int j = 0; j < 100; j++)
+ {
+ DataElement d;
+ map_.find (j,d);
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("%d:"), d.getData ()));
+ }
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\n")));
+
+ // Use the forward iterator.
+ this->iterate_forward ();
+
+ // Use the reverse iterator.
+ this->iterate_reverse ();
+
+ // Remove all the elements from the map.
+ this->remove_all ();
+
+ // Iterate through the map again.
+ this->iterate_forward ();
+
+ return 0;
+}
+
+void Hash_Map_Example::iterate_forward (void)
+{
+ ACE_TRACE (ACE_TEXT ("Hash_Map_Example::iterate_forward"));
+
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Forward Iteration \n")));
+ for (Hash_Map<int, DataElement>::iterator iter = map_.begin ();
+ iter != map_.end (); iter++)
+ {
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("%d:"), (*iter).int_id_.getData ()));
+ }
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\n")));
+}
+
+void Hash_Map_Example::iterate_reverse (void)
+{
+ ACE_TRACE (ACE_TEXT ("Hash_Map_Example::iterate_reverse"));
+
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Reverse Iteration \n")));
+ for (Hash_Map<int, DataElement>::reverse_iterator iter = map_.rbegin ();
+ iter != map_.rend (); iter++)
+ {
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("%d:"), (*iter).int_id_.getData ()));
+ }
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\n")));
+}
+
+void Hash_Map_Example::remove_all (void)
+{
+ ACE_TRACE (ACE_TEXT ("Hash_Map_Example::remove_all"));
+ map_.unbind_all ();
+}
+
+int ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ Hash_Map_Example me;
+ return me.run ();
+}
+
diff --git a/ACE/examples/APG/Containers/Hash_Map_Hash.cpp b/ACE/examples/APG/Containers/Hash_Map_Hash.cpp
new file mode 100644
index 00000000000..faad3c72585
--- /dev/null
+++ b/ACE/examples/APG/Containers/Hash_Map_Hash.cpp
@@ -0,0 +1,111 @@
+// $Id$
+
+#include "ace/Hash_Map_Manager.h"
+#include "ace/Synch.h" // Needed for the lock
+#include "ace/Functor.h"
+#include "DataElement.h"
+#include "Hash_Map_Hash.h"
+
+// Little helper class
+template<class EXT_ID, class INT_ID>
+class Hash_Map :
+ public ACE_Hash_Map_Manager_Ex<EXT_ID, INT_ID,
+ ACE_Hash<EXT_ID>, ACE_Equal_To<EXT_ID>, ACE_Null_Mutex>
+{};
+
+
+class Hash_Map_Example
+{
+public:
+ ~Hash_Map_Example ()
+ {
+ map_.close ();
+ }
+
+ // illustrate the hash map
+ int run (void);
+
+ // use the forward iterate
+ void iterate_forward (void);
+
+ // use the reverse iterator
+ void iterate_reverse (void);
+
+ // remove all the elements from the map
+ void remove_all (void);
+
+private:
+ Hash_Map<KeyType, DataElement> map_;
+};
+
+int Hash_Map_Example::run (void)
+{
+ ACE_TRACE (ACE_TEXT ("Hash_Map_Example::run"));
+
+ for (int i = 0; i < 100; i++)
+ {
+ map_.bind (i, DataElement (i));
+ }
+
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Map has \n")));
+ for (int j = 0; j < 100; j++)
+ {
+ DataElement d;
+ map_.find (j, d);
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("%d:"), d.getData ()));
+ }
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\n")));
+
+ // Use the forward iterator.
+ this->iterate_forward ();
+
+ // Use the reverse iterator.
+ this->iterate_reverse ();
+
+ // Remove all the elements from the map.
+ this->remove_all ();
+
+ // Iterate through the map again.
+ this->iterate_forward ();
+
+ return 0;
+}
+
+void Hash_Map_Example::iterate_forward (void)
+{
+ ACE_TRACE (ACE_TEXT ("Hash_Map_Example::iterate_forward"));
+
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Forward Iteration \n")));
+ for (Hash_Map<KeyType, DataElement>::iterator iter = map_.begin ();
+ iter != map_.end (); iter++)
+ {
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("%d:"), (*iter).int_id_.getData ()));
+ }
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\n")));
+}
+
+void Hash_Map_Example::iterate_reverse (void)
+{
+ ACE_TRACE (ACE_TEXT ("Hash_Map_Example::iterate_reverse"));
+
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Reverse Iteration \n")));
+ for (Hash_Map<KeyType, DataElement>::reverse_iterator iter = map_.rbegin ();
+ iter != map_.rend (); iter++)
+ {
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("%d:"), (*iter).int_id_.getData ()));
+ }
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\n")));
+}
+
+void Hash_Map_Example::remove_all (void)
+{
+ ACE_TRACE (ACE_TEXT ("Hash_Map_Example::remove_all"));
+ map_.unbind_all ();
+}
+
+int ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ Hash_Map_Example me;
+ return me.run ();
+}
+
diff --git a/ACE/examples/APG/Containers/Hash_Map_Hash.h b/ACE/examples/APG/Containers/Hash_Map_Hash.h
new file mode 100644
index 00000000000..a125f9ee7e6
--- /dev/null
+++ b/ACE/examples/APG/Containers/Hash_Map_Hash.h
@@ -0,0 +1,57 @@
+/* -*- C++ -*- */
+// $Id$
+
+#ifndef __HASH_MAP_HASH_H_
+#define __HASH_MAP_HASH_H_
+
+// Listing 1 code/ch05
+// Key type that we are going to use.
+class KeyType
+{
+public:
+ KeyType () : val_(0) {}
+
+ KeyType (int i) : val_(i) {}
+
+ KeyType (const KeyType& kt) { this->val_ = kt.val_; }
+
+ operator int (void) const { return val_; }
+
+private:
+ int val_;
+};
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+// Specialize the hash functor.
+template<>
+class ACE_Hash<KeyType>
+{
+public:
+ u_long operator() (const KeyType kt) const
+ {
+ int val = kt;
+ return (u_long)val;
+ }
+};
+
+
+// Specialize the equality functor.
+template<>
+class ACE_Equal_To<KeyType>
+{
+public:
+ int operator() (const KeyType& kt1,
+ const KeyType& kt2) const
+ {
+ int val1 = kt1;
+ int val2 = kt2;
+ return (val1 == val2);
+ }
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+// Listing 1
+
+#endif /* __HASH_MAP_HASH_H_ */
diff --git a/ACE/examples/APG/Containers/KeyType.h b/ACE/examples/APG/Containers/KeyType.h
new file mode 100644
index 00000000000..268b56c1684
--- /dev/null
+++ b/ACE/examples/APG/Containers/KeyType.h
@@ -0,0 +1,28 @@
+/* -*- C++ -*- */
+// $Id$
+
+#ifndef __KEYTYPE_H_
+#define __KEYTYPE_H_
+
+// Listing 1 code/ch05
+class KeyType
+{
+public:
+ friend bool operator == (const KeyType&, const KeyType&);
+
+ KeyType () : val_(0) {}
+ KeyType (int i) : val_(i) {}
+ KeyType (const KeyType& kt) { this->val_ = kt.val_; };
+ operator int() const { return val_; };
+
+private:
+ int val_;
+};
+
+bool operator == (const KeyType& a, const KeyType& b)
+{
+ return (a.val_ == b.val_);
+}
+// Listing 1
+
+#endif /* __KEYTYPE_H_ */
diff --git a/ACE/examples/APG/Containers/Makefile.am b/ACE/examples/APG/Containers/Makefile.am
new file mode 100644
index 00000000000..e5ef96ad6dc
--- /dev/null
+++ b/ACE/examples/APG/Containers/Makefile.am
@@ -0,0 +1,223 @@
+## Process this file with automake to create Makefile.in
+##
+## $Id$
+##
+## This file was generated by MPC. Any changes made directly to
+## this file will be lost the next time it is generated.
+##
+## MPC Command:
+## /acebuilds/ACE_wrappers-repository/bin/mwc.pl -include /acebuilds/MPC/config -include /acebuilds/MPC/templates -feature_file /acebuilds/ACE_wrappers-repository/local.features -noreldefs -type automake -exclude build,Kokyu
+
+ACE_BUILDDIR = $(top_builddir)
+ACE_ROOT = $(top_srcdir)
+
+
+## Makefile.Allocator.am
+noinst_PROGRAMS = Allocator
+
+Allocator_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+Allocator_SOURCES = \
+ Allocator.cpp \
+ DataElement.h \
+ Hash_Map_Hash.h \
+ KeyType.h \
+ RB_Tree_Functors.h
+
+Allocator_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Makefile.Array.am
+noinst_PROGRAMS += Array
+
+Array_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+Array_SOURCES = \
+ Array.cpp \
+ DataElement.h \
+ Hash_Map_Hash.h \
+ KeyType.h \
+ RB_Tree_Functors.h
+
+Array_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Makefile.Containers_Hash_Map.am
+noinst_PROGRAMS += Hash_Map
+
+Hash_Map_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+Hash_Map_SOURCES = \
+ Hash_Map.cpp \
+ DataElement.h \
+ Hash_Map_Hash.h \
+ KeyType.h \
+ RB_Tree_Functors.h
+
+Hash_Map_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Makefile.Containers_Map_Manager.am
+noinst_PROGRAMS += Map_Manager
+
+Map_Manager_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+Map_Manager_SOURCES = \
+ Map_Manager.cpp \
+ DataElement.h \
+ Hash_Map_Hash.h \
+ KeyType.h \
+ RB_Tree_Functors.h
+
+Map_Manager_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Makefile.DLList.am
+
+if !BUILD_ACE_FOR_TAO
+noinst_PROGRAMS += DLList
+
+DLList_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+DLList_SOURCES = \
+ DLList.cpp \
+ DataElement.h \
+ Hash_Map_Hash.h \
+ KeyType.h \
+ RB_Tree_Functors.h
+
+DLList_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+endif !BUILD_ACE_FOR_TAO
+
+## Makefile.Hash_Map_Hash.am
+noinst_PROGRAMS += Hash_Map_Hash
+
+Hash_Map_Hash_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+Hash_Map_Hash_SOURCES = \
+ Hash_Map_Hash.cpp \
+ Hash_Map_Hash.h
+
+Hash_Map_Hash_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Makefile.Map_Manager_Specialization.am
+noinst_PROGRAMS += Map_Manager_Specialization
+
+Map_Manager_Specialization_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+Map_Manager_Specialization_SOURCES = \
+ Map_Manager_Specialization.cpp \
+ DataElement.h \
+ Hash_Map_Hash.h \
+ KeyType.h \
+ RB_Tree_Functors.h
+
+Map_Manager_Specialization_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Makefile.Queues.am
+noinst_PROGRAMS += Queues
+
+Queues_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+Queues_SOURCES = \
+ Queues.cpp \
+ DataElement.h \
+ Hash_Map_Hash.h \
+ KeyType.h \
+ RB_Tree_Functors.h
+
+Queues_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Makefile.RB_Tree.am
+noinst_PROGRAMS += RB_Tree
+
+RB_Tree_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+RB_Tree_SOURCES = \
+ RB_Tree.cpp \
+ DataElement.h \
+ Hash_Map_Hash.h \
+ KeyType.h \
+ RB_Tree_Functors.h
+
+RB_Tree_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Makefile.RB_Tree_Functors.am
+noinst_PROGRAMS += RB_Tree_Functors
+
+RB_Tree_Functors_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+RB_Tree_Functors_SOURCES = \
+ RB_Tree_Functors.cpp \
+ RB_Tree_Functors.h
+
+RB_Tree_Functors_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Makefile.Sets.am
+noinst_PROGRAMS += Sets
+
+Sets_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+Sets_SOURCES = \
+ Sets.cpp \
+ DataElement.h \
+ Hash_Map_Hash.h \
+ KeyType.h \
+ RB_Tree_Functors.h
+
+Sets_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Makefile.Stacks.am
+noinst_PROGRAMS += Stacks
+
+Stacks_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+Stacks_SOURCES = \
+ Stacks.cpp \
+ DataElement.h \
+ Hash_Map_Hash.h \
+ KeyType.h \
+ RB_Tree_Functors.h
+
+Stacks_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Clean up template repositories, etc.
+clean-local:
+ -rm -f *~ *.bak *.rpo *.sym lib*.*_pure_* core core.*
+ -rm -f gcctemp.c gcctemp so_locations *.ics
+ -rm -rf cxx_repository ptrepository ti_files
+ -rm -rf templateregistry ir.out
+ -rm -rf ptrepository SunWS_cache Templates.DB
diff --git a/ACE/examples/APG/Containers/Map_Manager.cpp b/ACE/examples/APG/Containers/Map_Manager.cpp
new file mode 100644
index 00000000000..6673204fcc4
--- /dev/null
+++ b/ACE/examples/APG/Containers/Map_Manager.cpp
@@ -0,0 +1,117 @@
+// $Id$
+
+#include "ace/Log_Msg.h"
+#include "ace/Map_Manager.h"
+#include "ace/Synch.h"
+#include "DataElement.h"
+#include "KeyType.h"
+
+class Map_Example
+{
+public:
+ // Illustrate the ACE_Map_Manager.
+ int run (void);
+
+private:
+ // Iterate in the forward direction.
+ void iterate_forward (void);
+
+ // Iterate in the other direction.
+ void iterate_reverse (void);
+
+ // Remove all elements from the map.
+ void remove_all (void);
+
+private:
+ ACE_Map_Manager<KeyType,DataElement,ACE_Null_Mutex> map_;
+};
+
+// Listing 2 code/ch05
+int Map_Example::run (void)
+{
+ ACE_TRACE (ACE_TEXT ("Map_Example::run"));
+
+ // Corresponding KeyType objects are created on the fly.
+ for (int i = 0; i < 100; i++)
+ {
+ map_.bind (i, DataElement (i));
+ }
+
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Map has \n")));
+ for (int j = 0; j < 100; j++)
+ {
+ DataElement d;
+ map_.find (j,d);
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("%d:"), d.getData ()));
+ }
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\n")));
+
+ // Iterate in the forward direction.
+ this->iterate_forward ();
+
+ // Iterate in the other direction.
+ this->iterate_reverse ();
+
+ // Remove all elements from the map.
+ this->remove_all ();
+
+ // Iterate in the forward direction.
+ this->iterate_forward ();
+
+ return 0;
+}
+// Listing 2
+// Listing 3 code/ch05
+void Map_Example::iterate_forward (void)
+{
+ ACE_TRACE (ACE_TEXT ("Map_Example::iterate_forward"));
+
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Forward iteration\n")));
+ for (ACE_Map_Manager<KeyType,
+ DataElement,
+ ACE_Null_Mutex>::iterator
+ iter = map_.begin ();
+ iter != map_.end ();
+ iter++)
+ {
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("%d:"),
+ (*iter).int_id_.getData ()));
+ }
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\n")));
+}
+
+
+void Map_Example::iterate_reverse (void)
+{
+ ACE_TRACE (ACE_TEXT ("Map_Example::iterate_reverse"));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Reverse iteration\n")));
+ for (ACE_Map_Manager<KeyType,
+ DataElement,
+ ACE_Null_Mutex>::reverse_iterator
+ iter = map_.rbegin ();
+ iter != map_.end ();
+ iter++)
+ {
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("%d:"),
+ (*iter).int_id_.getData ()));
+ }
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\n")));
+}
+// Listing 3
+// Listing 4 code/ch05
+void Map_Example::remove_all (void)
+{
+ ACE_TRACE (ACE_TEXT ("Map_Example::remove_all"));
+
+ // Note that we can't use the iterators here as they
+ // are invalidated after deletions or insertions.
+ map_.unbind_all ();
+}
+// Listing 4
+
+int ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ Map_Example me;
+ return me.run ();
+}
+
diff --git a/ACE/examples/APG/Containers/Map_Manager_Specialization.cpp b/ACE/examples/APG/Containers/Map_Manager_Specialization.cpp
new file mode 100644
index 00000000000..fc9c00d86f0
--- /dev/null
+++ b/ACE/examples/APG/Containers/Map_Manager_Specialization.cpp
@@ -0,0 +1,153 @@
+// $Id$
+
+#include "ace/Log_Msg.h"
+#include "ace/Map_Manager.h"
+#include "ace/Synch.h" // Needed for the lock.
+#include "DataElement.h"
+#include "KeyType.h"
+
+/*
+** This needs to stay in the book for 2nd printing, but is the same as
+** what's in KeyType.h.
+*/
+#if 0
+// Listing 1 code/ch05
+class KeyType
+{
+public:
+ KeyType () : val_(0) {}
+
+ KeyType (int i) : val_(i) {}
+
+ KeyType (const KeyType& kt) { this->val_ = kt.val_; };
+
+ operator int () const { return val_; };
+
+private:
+ int val_;
+};
+
+template<>
+int
+ACE_Map_Manager<KeyType, DataElement, ACE_Null_Mutex>::equal
+(const KeyType& r1, const KeyType &r2)
+{
+ return (r1 == r2);
+}
+// Listing 1
+#else
+template<>
+int
+ACE_Map_Manager<KeyType, DataElement, ACE_Null_Mutex>::equal
+(const KeyType& r1, const KeyType &r2)
+{
+ return (r1 == r2);
+}
+#endif /* 0 */
+
+class Map_Example
+{
+public:
+ // Illustrate the ACE_Map_Manager<>.
+ int run (void);
+
+private:
+ // Iterate in the forward direction.
+ void iterate_forward (void);
+
+ // Iterate in the other direction.
+ void iterate_reverse (void);
+
+ // Remove all elements from the map.
+ void remove_all (void);
+
+private:
+ ACE_Map_Manager<KeyType,DataElement,ACE_Null_Mutex> map_;
+};
+
+int Map_Example::run (void)
+{
+ ACE_TRACE (ACE_TEXT ("Map_Example::run"));
+
+ // Corresponding KeyType objects are created on the fly.
+ for (int i = 0; i < 100; i++)
+ {
+ map_.bind (i, DataElement (i));
+ }
+
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Map has \n")));
+ for (int j = 0; j < 100; j++)
+ {
+ DataElement d;
+ int result = map_.find (j,d);
+ if (result == 0)
+ {
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("%d:"), d.getData ()));
+ }
+ }
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\n")));
+
+ // Iterate in the forward direction.
+ this->iterate_forward ();
+
+ // Iterate in the other direction.
+ this->iterate_reverse ();
+
+ // Remove all elements from the map.
+ this->remove_all ();
+
+ // Iterate in the forward direction.
+ this->iterate_forward ();
+
+ return 0;
+}
+
+void Map_Example::iterate_forward (void)
+{
+ ACE_TRACE (ACE_TEXT ("Map_Example::iterate_forward"));
+
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Forward iteration\n")));
+ for (ACE_Map_Manager<KeyType, DataElement, ACE_Null_Mutex>::iterator
+ iter = map_.begin ();
+ iter!= map_.end ();
+ iter++)
+ {
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("%d:"), (*iter).int_id_.getData ()));
+ }
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\n")));
+}
+
+void Map_Example::iterate_reverse (void)
+{
+ ACE_TRACE (ACE_TEXT ("Map_Example::iterate_reverse"));
+
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Reverse iteration\n")));
+ for (ACE_Map_Manager<KeyType, DataElement, ACE_Null_Mutex>::reverse_iterator
+ iter = map_.rbegin ();
+ iter!= map_.end ();
+ iter++)
+ {
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("%d:"), (*iter).int_id_.getData ()));
+ }
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\n")));
+}
+
+void Map_Example::remove_all (void)
+{
+ ACE_TRACE (ACE_TEXT ("Map_Example::remove_all"));
+
+ // Note that we can't use the iterators here
+ // as they are invalidated after deletions
+ // or insertions.
+ for (int i = 0; i < 100; i++)
+ {
+ map_.unbind (i);
+ }
+}
+
+int ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ Map_Example me;
+ return me.run ();
+}
+
diff --git a/ACE/examples/APG/Containers/Queues.cpp b/ACE/examples/APG/Containers/Queues.cpp
new file mode 100644
index 00000000000..ca945169ed4
--- /dev/null
+++ b/ACE/examples/APG/Containers/Queues.cpp
@@ -0,0 +1,115 @@
+// $Id$
+
+#include "ace/OS_Memory.h"
+#include "ace/Log_Msg.h"
+#include "ace/Containers.h"
+#include "DataElement.h"
+
+class QueueExample
+{
+public:
+ // Illustrate the various ACE Queues.
+ int run (void);
+
+private:
+ // Illustrate the ACE unbounded queue
+ // that has copies of the data elements.
+ int runStackUnboundedQueue (void);
+
+ // Illustrate the ACE unbounded queue
+ // with pointers to elements on the heap.
+ int runHeapUnboundedQueue (void);
+};
+
+int QueueExample::run (void)
+{
+ ACE_TRACE (ACE_TEXT ("QueueExample::run"));
+
+ // Illustrate the queue with elements on the stack.
+ if (this->runStackUnboundedQueue () != 0)
+ {
+ return -1;
+ }
+
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\n# of live objects %d\n"),
+ DataElement::numOfActiveObjects ()));
+
+ // Illustrate the queue with elements on the heap.
+ if (this->runHeapUnboundedQueue () != 0)
+ {
+ return -1;
+ }
+
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\n# of live objects %d\n"),
+ DataElement::numOfActiveObjects ()));
+
+ return 0;
+}
+
+// Listing 1 code/ch05
+int QueueExample::runStackUnboundedQueue (void)
+{
+ ACE_TRACE (ACE_TEXT ("QueueExample::runStackUnboundedQueue"));
+
+ ACE_Unbounded_Queue<DataElement> queue;
+ DataElement elem1[10];
+ int i;
+ for (i = 0; i < 10; i++)
+ {
+ elem1[i].setData (9-i);
+ queue.enqueue_head (elem1[i]);
+ }
+
+ DataElement elem2[10];
+ for (i = 0; i < 10; i++)
+ {
+ elem2[i].setData (i+10);
+ queue.enqueue_tail (elem2[i]);
+ }
+
+ for (ACE_Unbounded_Queue_Iterator<DataElement> iter (queue);
+ !iter.done ();
+ iter.advance ())
+ {
+ DataElement *elem = 0;
+ iter.next (elem);
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("%d:"), elem->getData ()));
+ }
+
+ return 0;
+}
+// Listing 1
+// Listing 2 code/ch05
+int QueueExample::runHeapUnboundedQueue (void)
+{
+ ACE_TRACE (ACE_TEXT ("QueueExample::runHeapUnboundedQueue"));
+
+ ACE_Unbounded_Queue<DataElement*> queue;
+ for (int i = 0; i < 20; i++)
+ {
+ DataElement *elem;
+ ACE_NEW_RETURN(elem, DataElement (i), -1);
+ queue.enqueue_head (elem);
+ }
+
+ for (ACE_Unbounded_Queue_Iterator<DataElement*> iter
+ = queue.begin ();
+ !iter.done ();
+ iter.advance ())
+ {
+ DataElement **elem = 0;
+ iter.next(elem);
+ ACE_DEBUG
+ ((LM_DEBUG, ACE_TEXT ("%d:"), (*elem)->getData ()));
+ delete (*elem);
+ }
+
+ return 0;
+}
+// Listing 2
+int ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ QueueExample que;
+ return que.run ();
+}
+
diff --git a/ACE/examples/APG/Containers/RB_Tree.cpp b/ACE/examples/APG/Containers/RB_Tree.cpp
new file mode 100644
index 00000000000..187332a31d8
--- /dev/null
+++ b/ACE/examples/APG/Containers/RB_Tree.cpp
@@ -0,0 +1,135 @@
+// $Id$
+
+#include "ace/RB_Tree.h"
+#include "ace/Log_Msg.h"
+#include "ace/Synch.h"
+#include "DataElement.h"
+
+// Little helper class.
+template<class EXT_ID, class INT_ID>
+class Tree : public ACE_RB_Tree<EXT_ID, INT_ID,
+ ACE_Less_Than<EXT_ID>,
+ ACE_Null_Mutex>
+{};
+
+class Tree_Example
+{
+public:
+ // Illustrate the tree.
+ int run (void);
+
+private:
+ // Use the forward iterator.
+ void iterate_forward (void);
+
+ // Use the reverse iterator.
+ void iterate_reverse (void);
+
+ // Remove all elements from the tree.
+ int remove_all (void);
+
+private:
+ Tree<int, DataElement*> tree_;
+};
+
+// Listing 1 code/ch05
+int Tree_Example::run (void)
+{
+ ACE_TRACE (ACE_TEXT ("Tree_Example::run"));
+
+ DataElement *d = 0;
+ for (int i = 0; i < 100; i++)
+ {
+ ACE_NEW_RETURN (d, DataElement (i), -1);
+ int result = tree_.bind (i, d);
+ if (result!= 0)
+ {
+ ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("%p\n"),
+ ACE_TEXT ("Bind")),
+ -1);
+ }
+ }
+
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Using find: \n")));
+ for (int j = 0; j < 100; j++)
+ {
+ tree_.find (j, d);
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("%d:"), d->getData ()));
+ }
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\n")));
+
+ // Use the forward iterator.
+ this->iterate_forward ();
+
+ // Use the reverse iterator.
+ this->iterate_reverse ();
+
+ // Remove all elements from the tree.
+ ACE_ASSERT (this->remove_all ()!= -1);
+
+ // Iterate through once again.
+ this->iterate_forward ();
+
+ return 0;
+}
+
+void Tree_Example::iterate_forward (void)
+{
+ ACE_TRACE (ACE_TEXT ("Tree_Example::iterate_forward"));
+
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Forward Iteration: \n")));
+ for (Tree<int, DataElement*>::iterator iter = tree_.begin ();
+ iter != tree_.end (); iter++)
+ {
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("%d:"),
+ (*iter).item ()->getData ()));
+ }
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\n")));
+}
+
+void Tree_Example::iterate_reverse (void)
+{
+ ACE_TRACE (ACE_TEXT ("Tree_Example::iterate_reverse"));
+
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Reverse Iteration: \n")));
+ for (Tree<int, DataElement*>::reverse_iterator iter
+ = tree_.rbegin ();
+ iter != tree_.rend (); iter++)
+ {
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("%d:"),
+ (*iter).item ()->getData ()));
+ }
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\n")));
+}
+
+int Tree_Example::remove_all (void)
+{
+ ACE_TRACE (ACE_TEXT ("Tree_Example::remove_all"));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Removing elements\n")));
+
+ // Note that we can't use the iterators here as they are
+ // invalidated after deletions or insertions.
+ for (int i = 0; i < 100; i++)
+ {
+ DataElement * d = 0;
+ int result = tree_.unbind (i, d);
+ if (result != 0)
+ {
+ ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("%p\n"),
+ ACE_TEXT ("Unbind")),
+ -1);
+ }
+ ACE_ASSERT (d!= 0);
+ delete d;
+ }
+
+ return 0;
+}
+// Listing 1
+
+int ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ Tree_Example te;
+ return te.run ();
+}
+
diff --git a/ACE/examples/APG/Containers/RB_Tree_Functors.cpp b/ACE/examples/APG/Containers/RB_Tree_Functors.cpp
new file mode 100644
index 00000000000..cb71fd75d79
--- /dev/null
+++ b/ACE/examples/APG/Containers/RB_Tree_Functors.cpp
@@ -0,0 +1,134 @@
+// $Id$
+
+#include "ace/Log_Msg.h"
+#include "DataElement.h"
+#include "RB_Tree_Functors.h"
+
+// Listing 0 code/ch05
+#include "ace/RB_Tree.h"
+#include "ace/Synch.h"
+
+// Little helper class.
+template<class EXT_ID, class INT_ID>
+class Tree : public ACE_RB_Tree<EXT_ID, INT_ID,
+ ACE_Less_Than<EXT_ID>,
+ ACE_Null_Mutex>
+{};
+// Listing 0
+
+class Tree_Example
+{
+public:
+ // Illustrate the tree.
+ int run (void);
+
+private:
+ // Use the forward iterator.
+ void iterate_forward (void);
+
+ // Use the reverse iterator.
+ void iterate_reverse (void);
+
+ // Remove all elements from the tree.
+ int remove_all (void);
+
+private:
+ Tree<KeyType, DataElement*> tree_;
+};
+
+
+int Tree_Example::run ()
+{
+ ACE_TRACE (ACE_TEXT ("Tree_Example::run"));
+
+ DataElement *d = 0;
+ for (int i = 0; i < 100; i++)
+ {
+ ACE_NEW_RETURN (d, DataElement (i), -1);
+ int result = tree_.bind(i, d);
+ if (result != 0)
+ {
+ ACE_ERROR_RETURN((LM_ERROR, "%p\n", "Bind"), -1);
+ }
+ }
+
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Using find: \n")));
+ for (int j = 0; j < 100; j++)
+ {
+ DataElement* d = 0;
+ int result = tree_.find (j, d);
+ if (result != 0)
+ {
+ ACE_ERROR_RETURN((LM_ERROR, "%p\n", "Find"), -1);
+ }
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("%d:"), d->getData ()));
+ }
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\n")));
+
+ // Use the forward iterator.
+ this->iterate_forward ();
+
+ // Use the reverse iterator.
+ this->iterate_reverse ();
+
+ // Remove all elements from the tree.
+ ACE_ASSERT (this->remove_all ()!= -1);
+
+ // Iterate through once again.
+ this->iterate_forward ();
+
+ return 0;
+}
+
+void Tree_Example::iterate_forward (void)
+{
+ ACE_TRACE (ACE_TEXT ("Tree_Example::iterate_forward"));
+
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Forward Iteration \n")));
+ for (Tree<KeyType, DataElement*>::iterator iter = tree_.begin ();
+ iter != tree_.end (); iter++)
+ {
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("%d:"), (*iter).item ()->getData ()));
+ }
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\n")));
+}
+
+void Tree_Example::iterate_reverse (void)
+{
+ ACE_TRACE (ACE_TEXT ("Tree_Example::iterate_reverse"));
+
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Reverse Iteration \n")));
+ for (Tree<KeyType, DataElement*>::reverse_iterator iter = tree_.rbegin ();
+ iter != tree_.rend (); iter++)
+ {
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("%d:"), (*iter).item ()->getData ()));
+ }
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\n")));
+}
+
+int Tree_Example::remove_all (void)
+{
+ ACE_TRACE (ACE_TEXT ("Tree_Example::remove_all"));
+
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Removing elements\n")));
+ for (int i = 0; i < 100; i++)
+ {
+ DataElement * d = 0;
+ int result = tree_.unbind (i, d);
+ if (result != 0)
+ {
+ ACE_ERROR_RETURN((LM_ERROR, "%p\n", "Unbind"), -1);
+ }
+ ACE_ASSERT (d != 0);
+ delete d;
+ }
+
+ return 0;
+}
+
+int ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ Tree_Example te;
+ return te.run ();
+}
+
diff --git a/ACE/examples/APG/Containers/RB_Tree_Functors.h b/ACE/examples/APG/Containers/RB_Tree_Functors.h
new file mode 100644
index 00000000000..010fb5fda62
--- /dev/null
+++ b/ACE/examples/APG/Containers/RB_Tree_Functors.h
@@ -0,0 +1,37 @@
+/* -*- C++ -*- */
+// $Id$
+
+#ifndef __RB_TREE_FUNCTORS_H_
+#define __RB_TREE_FUNCTORS_H_
+
+#include "ace/Functor.h"
+
+// Listing 1 code/ch05
+// Same key type.
+class KeyType
+{
+public:
+ KeyType () : val_(0) {}
+ KeyType (int i) : val_ (i) {}
+ KeyType (const KeyType& kt) { this->val_ = kt.val_; }
+ operator int() const { return val_; };
+
+private:
+ int val_;
+};
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+template<>
+class ACE_Less_Than<KeyType>
+{
+public:
+ int operator() (const KeyType k1, const KeyType k2)
+ { return k1 < k2; }
+};
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+// Listing 1
+
+#endif /* __RB_TREE_FUNCTORS_H_ */
diff --git a/ACE/examples/APG/Containers/Sets.cpp b/ACE/examples/APG/Containers/Sets.cpp
new file mode 100644
index 00000000000..3eaec6f7bec
--- /dev/null
+++ b/ACE/examples/APG/Containers/Sets.cpp
@@ -0,0 +1,123 @@
+// $Id$
+
+#include "ace/OS_Memory.h"
+#include "ace/Log_Msg.h"
+#include "ace/Containers.h"
+#include "DataElement.h"
+
+class SetExample
+{
+public:
+ // Illustrate all ACE set types.
+ int run (void);
+
+private:
+ // Illustrate the ACE Bounded Sets.
+ int runBoundedSet (void);
+
+ // Illustrate the ACE Unbounded sets.
+ int runUnboundedSet (void);
+};
+
+int SetExample::run (void)
+{
+ ACE_TRACE (ACE_TEXT ("SetExample::run"));
+
+ ACE_ASSERT (!this->runBoundedSet ());
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\n# of live objects %d\n"),
+ DataElement::numOfActiveObjects ()));
+
+ ACE_ASSERT (!this->runUnboundedSet ());
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\n# of live objects %d\n"),
+ DataElement::numOfActiveObjects ()));
+
+ return 0;
+}
+// Listing 1 code/ch05
+int SetExample::runBoundedSet ()
+{
+ ACE_TRACE (ACE_TEXT ("SetExample::runBoundedSet"));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Using a bounded set\n")));
+ ACE_Bounded_Set<DataElement> bset (100);
+
+ DataElement elem[100];
+ for (int i = 0; i < 100; i++)
+ {
+ elem[i].setData (i);
+
+ // Inserting two copies of the same element isn't allowed.
+ bset.insert (elem[i]);
+ if (bset.insert (elem[i]) == -1)
+ {
+ ACE_DEBUG ((LM_ERROR, ACE_TEXT ("%p\n"),
+ ACE_TEXT ("insert set")));
+ }
+ }
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("%d\n"),
+ DataElement::numOfActiveObjects ()));
+
+ DataElement elem1 (10), elem2 (99);
+ if (!bset.find (elem1) && !bset.find (elem2))
+ {
+ ACE_DEBUG ((LM_INFO,
+ ACE_TEXT ("The elements %d and %d are ")
+ ACE_TEXT ("in the set!\n"),
+ elem1.getData (), elem2.getData ()));
+ }
+
+ for (int j = 0; j < 50; j++)
+ {
+ bset.remove (elem[j]); // Remove the element from the set.
+ ACE_DEBUG
+ ((LM_DEBUG, ACE_TEXT ("%d:"), elem[j].getData ()));
+ }
+
+ if ((bset.find (elem[0]) == -1) && (bset.find (elem[49]) == -1))
+ {
+ ACE_DEBUG ((LM_INFO,
+ ACE_TEXT ("The elements %d and %d are ")
+ ACE_TEXT ("NOT in the set!\n"),
+ elem[0].getData (), elem[99].getData ()));
+ }
+
+ return 0;
+}
+// Listing 1
+// Listing 2 code/ch05
+int SetExample::runUnboundedSet ()
+{
+ ACE_TRACE (ACE_TEXT ("SetExample::runUnboundedSet"));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Using an unbounded set.\n")));
+ ACE_Unbounded_Set<DataElement*> uset;
+ for (int m = 0; m < 100; m++)
+ {
+ DataElement *elem;
+ ACE_NEW_RETURN (elem, DataElement (m), -1);
+ uset.insert (elem);
+ }
+ DataElement deBegin (0), deEnd (99);
+ if (!uset.find (&deBegin) && !uset.find (&deEnd))
+ {
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Found the elements\n")));
+ }
+
+ // Iterate and destroy the elements in the set.
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Deleting the elements\n")));
+ ACE_Unbounded_Set_Iterator<DataElement*> iter (uset);
+ for (iter = uset.begin (); iter != uset.end (); iter++)
+ {
+ DataElement* elem = (*iter);
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("%d:"), elem->getData ()));
+ delete elem;
+ }
+
+ return 0;
+}
+// Listing 2
+
+int ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ SetExample se;
+ se.run ();
+ return 0;
+}
diff --git a/ACE/examples/APG/Containers/Stacks.cpp b/ACE/examples/APG/Containers/Stacks.cpp
new file mode 100644
index 00000000000..b02a243ab92
--- /dev/null
+++ b/ACE/examples/APG/Containers/Stacks.cpp
@@ -0,0 +1,147 @@
+// $Id$
+
+#include "ace/OS_Memory.h"
+#include "ace/Log_Msg.h"
+#include "ace/Containers.h"
+#include "DataElement.h"
+
+class StackExample
+{
+public:
+ StackExample (): privateStack_(100) {}
+
+ // Illustrate all the differnet
+ // types of stacks provided by ACE.
+ int run (void);
+
+private:
+ // Illustrate the use of a bounded stack.
+ int runBoundedStack (void);
+
+ // Illustrate the use of an unbounded stack.
+ int runUnboundedStack (void);
+
+ // Illustrate the use of a compile time fixed stack.
+ int runFixedStack (void);
+
+private:
+ ACE_Bounded_Stack<DataElement*> privateStack_;
+};
+
+int StackExample::run (void)
+{
+ ACE_TRACE (ACE_TEXT ("StackUser::run"));
+
+ ACE_ASSERT(!this->runBoundedStack());
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\n# of live objects %d\n"),
+ DataElement::numOfActiveObjects()));
+
+ ACE_ASSERT(!this->runFixedStack());
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\n# of live objects %d\n"),
+ DataElement::numOfActiveObjects()));
+
+ ACE_ASSERT(!this->runUnboundedStack());
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\n# of live objects %d\n"),
+ DataElement::numOfActiveObjects()));
+
+ return 0;
+}
+// Listing 1 code/ch05
+int StackExample::runBoundedStack (void)
+{
+ ACE_TRACE (ACE_TEXT ("StackExample::runBoundedStack"));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Using a bounded stack\n")));
+
+ ACE_Bounded_Stack<DataElement> bstack1 (100);
+
+ // The element array is constrained to this scope.
+ {
+ DataElement elem[100];
+ for (int i = 0; i < 100; i++)
+ {
+ elem[i].setData(i);
+ // Push the element on the stack.
+ bstack1.push (elem[i]);
+ }
+ }
+
+ ACE_Bounded_Stack<DataElement> bstack2 (100);
+
+ // Make a copy!
+ bstack2 = bstack1;
+ for (int j = 0; j < 100; j++)
+ {
+ DataElement elem;
+ bstack2.pop (elem);
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("%d:"), elem.getData ()));
+ }
+
+ return 0;
+}
+// Listing 1
+// Listing 2 code/ch05
+int StackExample::runFixedStack (void)
+{
+ ACE_TRACE (ACE_TEXT ("StackExample::runFixedStack"));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Using a fixed stack\n")));
+
+ ACE_Fixed_Stack<DataElement*, 100> fstack;
+ for (int k = 0; k < 100; k++)
+ {
+ DataElement* elem;
+ ACE_NEW_RETURN(elem, DataElement (k), -1);
+ fstack.push (elem); // Push the element on the stack.
+ }
+
+ for (int l = 0; l < 100; l++)
+ {
+ DataElement* elem = 0;
+ fstack.pop (elem);
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("%d:"), elem->getData ()));
+ delete elem;
+ }
+
+ return 0;
+}
+
+int StackExample::runUnboundedStack (void)
+{
+ ACE_TRACE (ACE_TEXT ("StackExample::runUnboundedStack"));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Using an unbounded stack\n")));
+
+ ACE_Unbounded_Stack<DataElement*> ustack;
+ for (int m = 0; m < 100; m++)
+ {
+ DataElement *elem;
+ ACE_NEW_RETURN(elem, DataElement (m), -1);
+ // Push the element on both stacks.
+ ustack.push (elem);
+ privateStack_.push (elem);
+ }
+
+ // Oddly enough, you can actually iterate through an
+ // unbounded stack! This is because underneath the covers
+ // the unbounded stack is a linked list.
+
+ // This will cause the elements in the private stack to
+ // also disappear!
+ ACE_Unbounded_Stack_Iterator<DataElement*> iter (ustack);
+ for (iter.first (); !iter.done (); iter.advance ())
+ {
+ DataElement** elem = 0;
+ iter.next (elem);
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("%d:"),
+ (*elem)->getData ()));
+ delete (*elem);
+ }
+
+ return 0;
+}
+// Listing 2
+
+int ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ StackExample se;
+ return se.run ();
+}
+
diff --git a/ACE/examples/APG/Containers/containers.mpc b/ACE/examples/APG/Containers/containers.mpc
new file mode 100644
index 00000000000..d08ef9133aa
--- /dev/null
+++ b/ACE/examples/APG/Containers/containers.mpc
@@ -0,0 +1,87 @@
+// -*- MPC -*-
+// $Id$
+
+project(DLList) : aceexe {
+ avoids += ace_for_tao
+ exename = DLList
+ Source_Files {
+ DLList.cpp
+ }
+}
+
+project(Stacks) : aceexe {
+ exename = Stacks
+ Source_Files {
+ Stacks.cpp
+ }
+}
+
+project(Queues) : aceexe {
+ exename = Queues
+ Source_Files {
+ Queues.cpp
+ }
+}
+
+project(Array) : aceexe {
+ exename = Array
+ Source_Files {
+ Array.cpp
+ }
+}
+
+project(Sets) : aceexe {
+ exename = Sets
+ Source_Files {
+ Sets.cpp
+ }
+}
+
+project(*Map Manager) : aceexe {
+ exename = Map_Manager
+ Source_Files {
+ Map_Manager.cpp
+ }
+}
+
+project(Map Manager Specialization) : aceexe {
+ exename = Map_Manager_Specialization
+ Source_Files {
+ Map_Manager_Specialization.cpp
+ }
+}
+
+project(*Hash Map) : aceexe {
+ exename = Hash_Map
+ Source_Files {
+ Hash_Map.cpp
+ }
+}
+
+project(Hash Map Hash) : aceexe {
+ exename = Hash_Map_Hash
+ Source_Files {
+ Hash_Map_Hash.cpp
+ }
+}
+
+project(RB Tree) : aceexe {
+ exename = RB_Tree
+ Source_Files {
+ RB_Tree.cpp
+ }
+}
+
+project(RB Tree Functors) : aceexe {
+ exename = RB_Tree_Functors
+ Source_Files {
+ RB_Tree_Functors.cpp
+ }
+}
+
+project(Allocator) : aceexe {
+ exename = Allocator
+ Source_Files {
+ Allocator.cpp
+ }
+}
diff --git a/ACE/examples/APG/Logging/.cvsignore b/ACE/examples/APG/Logging/.cvsignore
new file mode 100644
index 00000000000..821ee0bc87c
--- /dev/null
+++ b/ACE/examples/APG/Logging/.cvsignore
@@ -0,0 +1,36 @@
+Change_Instance_Default
+Change_Instance_Default
+Change_Mask
+Change_Mask
+Howto_Syslog
+Howto_Syslog
+Simple1
+Simple1
+Simple2
+Simple2
+Trace_Return
+Trace_Return
+Use_Callback
+Use_Callback
+Use_Callback2
+Use_Callback2
+Use_LogManager
+Use_LogManager
+Use_Logger
+Use_Logger
+Use_Logging_Server
+Use_Logging_Server
+Use_Logging_Strategy
+Use_Logging_Strategy
+Use_Multiple_Sinks
+Use_Multiple_Sinks
+Use_Ostream
+Use_Ostream
+Use_Stderr
+Use_Stderr
+Use_Syslog
+Use_Syslog
+Wrap_Macros
+Wrap_Macros
+Wrap_Macros_Alt
+Wrap_Macros_Alt
diff --git a/ACE/examples/APG/Logging/Callback-2.h b/ACE/examples/APG/Logging/Callback-2.h
new file mode 100644
index 00000000000..906b2e43286
--- /dev/null
+++ b/ACE/examples/APG/Logging/Callback-2.h
@@ -0,0 +1,44 @@
+// $Id$
+
+#ifndef APG_CALLBACK2_H
+#define APG_CALLBACK2_H
+
+#include "ace/OS_NS_time.h"
+#include "ace/streams.h"
+#include "ace/Log_Msg_Callback.h"
+#include "ace/Log_Record.h"
+#include "ace/SString.h"
+#include "ace/Time_Value.h"
+
+class Callback : public ACE_Log_Msg_Callback
+{
+public:
+ void log (ACE_Log_Record &log_record)
+ {
+ cerr << "Log Message Received:" << endl;
+ unsigned long msg_severity = log_record.type ();
+ ACE_Log_Priority prio =
+ static_cast<ACE_Log_Priority> (msg_severity);
+ const ACE_TCHAR *prio_name =
+ ACE_Log_Record::priority_name (prio);
+ cerr << "\tType: "
+ << ACE_TEXT_ALWAYS_CHAR (prio_name)
+ << endl;
+
+ cerr << "\tLength: " << log_record.length () << endl;
+
+ const time_t epoch = log_record.time_stamp ().sec ();
+ cerr << "\tTime_Stamp: "
+ << ACE_TEXT_ALWAYS_CHAR (ACE_OS::ctime (&epoch))
+ << flush;
+
+ cerr << "\tPid: " << log_record.pid () << endl;
+
+ ACE_CString data (">> ");
+ data += ACE_TEXT_ALWAYS_CHAR (log_record.msg_data ());
+
+ cerr << "\tMsgData: " << data.c_str () << endl;
+ }
+};
+
+#endif /* APG_CALLBACK2_H */
diff --git a/ACE/examples/APG/Logging/Callback-3.h b/ACE/examples/APG/Logging/Callback-3.h
new file mode 100644
index 00000000000..22824fad382
--- /dev/null
+++ b/ACE/examples/APG/Logging/Callback-3.h
@@ -0,0 +1,69 @@
+// $Id$
+
+#ifndef APG_CALLBACK3_H
+#define APG_CALLBACK3_H
+
+#include "ace/streams.h"
+#include "ace/Log_Msg.h"
+#include "ace/Log_Msg_Callback.h"
+#include "ace/Log_Record.h"
+#include "ace/SOCK_Stream.h"
+#include "ace/SOCK_Connector.h"
+#include "ace/INET_Addr.h"
+
+#define LOGGER_PORT 20009
+
+class Callback : public ACE_Log_Msg_Callback
+{
+public:
+ Callback ()
+ {
+ this->logger_ = new ACE_SOCK_Stream;
+ ACE_SOCK_Connector connector;
+ ACE_INET_Addr addr (LOGGER_PORT, ACE_DEFAULT_SERVER_HOST);
+
+ if (connector.connect (*(this->logger_), addr) == -1)
+ {
+ delete this->logger_;
+ this->logger_ = 0;
+ }
+ }
+
+ virtual ~Callback ()
+ {
+ if (this->logger_)
+ {
+ this->logger_->close ();
+ }
+ delete this->logger_;
+ }
+
+ void log (ACE_Log_Record &log_record)
+ {
+ if (!this->logger_)
+ {
+# if defined (ACE_LACKS_IOSTREAM_TOTALLY)
+ log_record.print
+ (ACE_TEXT (""), ACE_Log_Msg::VERBOSE, stderr);
+# else
+ log_record.print
+ (ACE_TEXT (""), ACE_Log_Msg::VERBOSE, cerr);
+# endif /* ACE_LACKS_IOSTREAM_TOTALLY */
+ return;
+ }
+
+ size_t len = log_record.length();
+ log_record.encode ();
+
+ if (this->logger_->send_n ((char *) &log_record, len) == -1)
+ {
+ delete this->logger_;
+ this->logger_ = 0;
+ }
+ }
+
+private:
+ ACE_SOCK_Stream *logger_;
+};
+
+#endif /* APG_CALLBACK3_H */
diff --git a/ACE/examples/APG/Logging/Callback.h b/ACE/examples/APG/Logging/Callback.h
new file mode 100644
index 00000000000..86dff9ea826
--- /dev/null
+++ b/ACE/examples/APG/Logging/Callback.h
@@ -0,0 +1,25 @@
+// $Id$
+
+#ifndef APG_CALLBACK_H
+#define APG_CALLBACK_H
+
+#include "ace/streams.h"
+#include "ace/Log_Msg.h"
+#include "ace/Log_Msg_Callback.h"
+#include "ace/Log_Record.h"
+
+class Callback : public ACE_Log_Msg_Callback
+{
+public:
+ void log (ACE_Log_Record &log_record) {
+# if defined (ACE_LACKS_IOSTREAM_TOTALLY)
+ log_record.print (ACE_TEXT (""), 0, stderr);
+ log_record.print (ACE_TEXT (""), ACE_Log_Msg::VERBOSE, stderr);
+# else
+ log_record.print (ACE_TEXT (""), 0, cerr);
+ log_record.print (ACE_TEXT (""), ACE_Log_Msg::VERBOSE, cerr);
+# endif /* ACE_LACKS_IOSTREAM_TOTALLY */
+ }
+};
+
+#endif /* APG_CALLBACK_H */
diff --git a/ACE/examples/APG/Logging/Change_Instance_Default.cpp b/ACE/examples/APG/Logging/Change_Instance_Default.cpp
new file mode 100644
index 00000000000..e22af840259
--- /dev/null
+++ b/ACE/examples/APG/Logging/Change_Instance_Default.cpp
@@ -0,0 +1,37 @@
+/**
+ * $Id$
+ *
+ * Sample code from The ACE Programmer's Guide,
+ * Copyright 2003 Addison-Wesley. All Rights Reserved.
+ *
+ * This code shows how to set the ACE_Log_Msg per-instance default
+ * differently for groups of spawned threads.
+ */
+
+#include "ace/Log_Msg.h"
+#include "ace/Thread_Manager.h"
+
+ACE_THR_FUNC_RETURN worker (void *)
+{
+ // do some work
+ return 0;
+}
+
+ACE_THR_FUNC_RETURN service (void *)
+{
+ // run the service
+ return 0;
+}
+
+int ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ // Listing 1 code/ch03
+ ACE_LOG_MSG->priority_mask (0, ACE_Log_Msg::PROCESS);
+ ACE_Log_Msg::enable_debug_messages ();
+ ACE_Thread_Manager::instance ()->spawn (service);
+ ACE_Log_Msg::disable_debug_messages ();
+ ACE_Thread_Manager::instance ()->spawn_n (3, worker);
+ // Listing 1
+ ACE_Thread_Manager::instance ()->wait ();
+ return 0;
+}
diff --git a/ACE/examples/APG/Logging/Change_Mask.cpp b/ACE/examples/APG/Logging/Change_Mask.cpp
new file mode 100644
index 00000000000..a34a00e63b1
--- /dev/null
+++ b/ACE/examples/APG/Logging/Change_Mask.cpp
@@ -0,0 +1,29 @@
+// $Id$
+
+#include "ace/Log_Msg.h"
+
+void foo (void);
+
+int ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ ACE_TRACE ("main");
+
+ // Listing 1 code/ch03
+ ACE_LOG_MSG->priority_mask (0, ACE_Log_Msg::PROCESS);
+ ACE_LOG_MSG->priority_mask (LM_DEBUG | LM_NOTICE,
+ ACE_Log_Msg::THREAD);
+ // Listing 1
+
+ ACE_DEBUG ((LM_INFO, ACE_TEXT ("%IHi Mom\n")));
+ foo ();
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("%IGoodnight\n")));
+
+ return 0;
+}
+
+void foo (void)
+{
+ ACE_TRACE ("foo");
+
+ ACE_DEBUG ((LM_NOTICE, ACE_TEXT ("%IHowdy Pardner\n")));
+}
diff --git a/ACE/examples/APG/Logging/Howto_Syslog.cpp b/ACE/examples/APG/Logging/Howto_Syslog.cpp
new file mode 100644
index 00000000000..283099a3da1
--- /dev/null
+++ b/ACE/examples/APG/Logging/Howto_Syslog.cpp
@@ -0,0 +1,28 @@
+// $Id$
+
+#include "ace/Log_Msg.h"
+
+void foo (void);
+
+// Listing 1 code/ch03
+int ACE_TMAIN (int, ACE_TCHAR *argv[])
+{
+ ACE_LOG_MSG->open
+ (argv[0], ACE_Log_Msg::SYSLOG, ACE_TEXT ("syslogTest"));
+ // Listing 1
+
+ ACE_TRACE ("main");
+
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("%IHi Mom\n")));
+ foo ();
+ ACE_DEBUG ((LM_INFO, ACE_TEXT ("%IGoodnight\n")));
+
+ return 0;
+}
+
+void foo (void)
+{
+ ACE_TRACE ("foo");
+
+ ACE_DEBUG ((LM_INFO, ACE_TEXT ("%IHowdy Pardner\n")));
+}
diff --git a/ACE/examples/APG/Logging/LogManager.h b/ACE/examples/APG/Logging/LogManager.h
new file mode 100644
index 00000000000..2cf8c7f7d48
--- /dev/null
+++ b/ACE/examples/APG/Logging/LogManager.h
@@ -0,0 +1,102 @@
+// $Id$
+
+#include "ace/streams.h"
+#include "ace/Synch.h"
+#include "ace/Singleton.h"
+#include "ace/Log_Msg.h"
+#include "ace/Log_Msg_Callback.h"
+
+#ifndef LOG_MANAGER_H
+#define LOG_MANAGER_H
+
+// Listing 1 code/ch03
+class LogManager
+{
+public:
+ LogManager ();
+ ~LogManager ();
+
+ void redirectToDaemon
+ (const ACE_TCHAR *prog_name = ACE_TEXT (""));
+ void redirectToSyslog
+ (const ACE_TCHAR *prog_name = ACE_TEXT (""));
+ void redirectToOStream (ACE_OSTREAM_TYPE *output);
+ void redirectToFile (const char *filename);
+ void redirectToStderr (void);
+ ACE_Log_Msg_Callback * redirectToCallback
+ (ACE_Log_Msg_Callback *callback);
+
+ // Exclude 1
+private:
+ ofstream *log_stream_;
+ ACE_OSTREAM_TYPE *output_stream_;
+ // Exclude 1
+};
+// Listing 1
+
+// Listing 2 code/ch03
+LogManager::LogManager ()
+ : log_stream_ (0), output_stream_ (0)
+{ }
+
+LogManager::~LogManager ()
+{
+ if (log_stream_)
+ log_stream_->close ();
+ delete log_stream_;
+}
+
+void LogManager::redirectToSyslog (const ACE_TCHAR *prog_name)
+{
+ ACE_LOG_MSG->open (prog_name, ACE_Log_Msg::SYSLOG, prog_name);
+}
+
+void LogManager::redirectToDaemon (const ACE_TCHAR *prog_name)
+{
+ ACE_LOG_MSG->open (prog_name, ACE_Log_Msg::LOGGER,
+ ACE_DEFAULT_LOGGER_KEY);
+}
+
+void LogManager::redirectToOStream (ACE_OSTREAM_TYPE *output)
+{
+ output_stream_ = output;
+ ACE_LOG_MSG->msg_ostream (this->output_stream_);
+ ACE_LOG_MSG->clr_flags
+ (ACE_Log_Msg::STDERR | ACE_Log_Msg::LOGGER);
+ ACE_LOG_MSG->set_flags (ACE_Log_Msg::OSTREAM);
+}
+
+void LogManager::redirectToFile (const char *filename)
+{
+ log_stream_ = new ofstream ();
+ log_stream_->open (filename, ios::out | ios::app);
+ this->redirectToOStream ((ACE_OSTREAM_TYPE *)log_stream_);
+}
+
+void LogManager::redirectToStderr (void)
+{
+ ACE_LOG_MSG->clr_flags
+ (ACE_Log_Msg::OSTREAM | ACE_Log_Msg::LOGGER);
+ ACE_LOG_MSG->set_flags (ACE_Log_Msg::STDERR);
+}
+
+ACE_Log_Msg_Callback *
+LogManager::redirectToCallback (ACE_Log_Msg_Callback * callback)
+{
+ ACE_Log_Msg_Callback *previous =
+ ACE_LOG_MSG->msg_callback (callback);
+ if (callback == 0)
+ ACE_LOG_MSG->clr_flags (ACE_Log_Msg::MSG_CALLBACK);
+ else
+ ACE_LOG_MSG->set_flags (ACE_Log_Msg::MSG_CALLBACK);
+ return previous;
+}
+// Listing 2
+
+// Listing 3 code/ch03
+typedef ACE_Singleton<LogManager, ACE_Null_Mutex>
+ LogManagerSingleton;
+#define LOG_MANAGER LogManagerSingleton::instance()
+// Listing 3
+
+#endif /* LOG_MANAGER_H */
diff --git a/ACE/examples/APG/Logging/Log_Msg_Alt.h b/ACE/examples/APG/Logging/Log_Msg_Alt.h
new file mode 100644
index 00000000000..c78d2bd1f4a
--- /dev/null
+++ b/ACE/examples/APG/Logging/Log_Msg_Alt.h
@@ -0,0 +1,19 @@
+// $Id$
+
+#ifndef LOG_MSG_ALT_H
+#define LOG_MSG_ALT_H
+
+#include "ace/Log_Msg.h"
+
+// Listing 1 code/ch03
+#define MY_DEBUG LM_DEBUG, ACE_TEXT ("DEBUG%I")
+#define MY_INFO LM_INFO, ACE_TEXT ("INFO%I")
+#define MY_NOTICE LM_NOTICE, ACE_TEXT ("NOTICE%I")
+#define MY_WARNING LM_WARNING, ACE_TEXT ("WARNING%I")
+#define MY_ERROR LM_ERROR, ACE_TEXT ("ERROR%I")
+#define MY_CRITICAL LM_CRITICAL, ACE_TEXT ("CRITICAL%I")
+#define MY_ALERT LM_ALERT, ACE_TEXT ("ALERT%I")
+#define MY_EMERGENCY LM_EMERGENCY, ACE_TEXT ("EMERGENCY%I")
+// Listing 1
+
+#endif /* LOG_ALT_H */
diff --git a/ACE/examples/APG/Logging/Makefile.am b/ACE/examples/APG/Logging/Makefile.am
new file mode 100644
index 00000000000..69564edb197
--- /dev/null
+++ b/ACE/examples/APG/Logging/Makefile.am
@@ -0,0 +1,362 @@
+## Process this file with automake to create Makefile.in
+##
+## $Id$
+##
+## This file was generated by MPC. Any changes made directly to
+## this file will be lost the next time it is generated.
+##
+## MPC Command:
+## /acebuilds/ACE_wrappers-repository/bin/mwc.pl -include /acebuilds/MPC/config -include /acebuilds/MPC/templates -feature_file /acebuilds/ACE_wrappers-repository/local.features -noreldefs -type automake -exclude build,Kokyu
+
+ACE_BUILDDIR = $(top_builddir)
+ACE_ROOT = $(top_srcdir)
+
+## Makefile.Change_Instance_Default.am
+noinst_PROGRAMS = Change_Instance_Default
+
+Change_Instance_Default_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+Change_Instance_Default_SOURCES = \
+ Change_Instance_Default.cpp \
+ Callback-2.h \
+ Callback-3.h \
+ Callback.h \
+ LogManager.h \
+ Log_Msg_Alt.h \
+ Trace.h
+
+Change_Instance_Default_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Makefile.Change_Mask.am
+noinst_PROGRAMS += Change_Mask
+
+Change_Mask_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+Change_Mask_SOURCES = \
+ Change_Mask.cpp \
+ Callback-2.h \
+ Callback-3.h \
+ Callback.h \
+ LogManager.h \
+ Log_Msg_Alt.h \
+ Trace.h
+
+Change_Mask_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Makefile.Howto_Syslog.am
+noinst_PROGRAMS += Howto_Syslog
+
+Howto_Syslog_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+Howto_Syslog_SOURCES = \
+ Howto_Syslog.cpp \
+ Callback-2.h \
+ Callback-3.h \
+ Callback.h \
+ LogManager.h \
+ Log_Msg_Alt.h \
+ Trace.h
+
+Howto_Syslog_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Makefile.Simple1.am
+noinst_PROGRAMS += Simple1
+
+Simple1_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+Simple1_SOURCES = \
+ Simple1.cpp \
+ Callback-2.h \
+ Callback-3.h \
+ Callback.h \
+ LogManager.h \
+ Log_Msg_Alt.h \
+ Trace.h
+
+Simple1_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Makefile.Simple2.am
+noinst_PROGRAMS += Simple2
+
+Simple2_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+Simple2_SOURCES = \
+ Simple2.cpp \
+ Callback-2.h \
+ Callback-3.h \
+ Callback.h \
+ LogManager.h \
+ Log_Msg_Alt.h \
+ Trace.h
+
+Simple2_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Makefile.Trace_Return.am
+noinst_PROGRAMS += Trace_Return
+
+Trace_Return_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+Trace_Return_SOURCES = \
+ Trace_Return.cpp \
+ Callback-2.h \
+ Callback-3.h \
+ Callback.h \
+ LogManager.h \
+ Log_Msg_Alt.h \
+ Trace.h
+
+Trace_Return_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Makefile.Use_Callback.am
+noinst_PROGRAMS += Use_Callback
+
+Use_Callback_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+Use_Callback_SOURCES = \
+ Use_Callback.cpp \
+ Callback-2.h \
+ Callback-3.h \
+ Callback.h \
+ LogManager.h \
+ Log_Msg_Alt.h \
+ Trace.h
+
+Use_Callback_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Makefile.Use_Callback2.am
+noinst_PROGRAMS += Use_Callback2
+
+Use_Callback2_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+Use_Callback2_SOURCES = \
+ Use_Callback2.cpp \
+ Callback-2.h \
+ Callback-3.h \
+ Callback.h \
+ LogManager.h \
+ Log_Msg_Alt.h \
+ Trace.h
+
+Use_Callback2_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Makefile.Use_LogManager.am
+noinst_PROGRAMS += Use_LogManager
+
+Use_LogManager_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+Use_LogManager_SOURCES = \
+ Use_LogManager.cpp \
+ Callback-2.h \
+ Callback-3.h \
+ Callback.h \
+ LogManager.h \
+ Log_Msg_Alt.h \
+ Trace.h
+
+Use_LogManager_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Makefile.Use_Logger.am
+noinst_PROGRAMS += Use_Logger
+
+Use_Logger_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+Use_Logger_SOURCES = \
+ Use_Logger.cpp \
+ Callback-2.h \
+ Callback-3.h \
+ Callback.h \
+ LogManager.h \
+ Log_Msg_Alt.h \
+ Trace.h
+
+Use_Logger_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Makefile.Use_Logging_Server.am
+noinst_PROGRAMS += Use_Logging_Server
+
+Use_Logging_Server_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+Use_Logging_Server_SOURCES = \
+ Use_Logging_Server.cpp \
+ Callback-2.h \
+ Callback-3.h \
+ Callback.h \
+ LogManager.h \
+ Log_Msg_Alt.h \
+ Trace.h
+
+Use_Logging_Server_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Makefile.Use_Logging_Strategy.am
+noinst_PROGRAMS += Use_Logging_Strategy
+
+Use_Logging_Strategy_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+Use_Logging_Strategy_SOURCES = \
+ Use_Logging_Strategy.cpp \
+ Callback-2.h \
+ Callback-3.h \
+ Callback.h \
+ LogManager.h \
+ Log_Msg_Alt.h \
+ Trace.h
+
+Use_Logging_Strategy_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Makefile.Use_Multiple_Sinks.am
+noinst_PROGRAMS += Use_Multiple_Sinks
+
+Use_Multiple_Sinks_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+Use_Multiple_Sinks_SOURCES = \
+ Use_Multiple_Sinks.cpp \
+ Callback-2.h \
+ Callback-3.h \
+ Callback.h \
+ LogManager.h \
+ Log_Msg_Alt.h \
+ Trace.h
+
+Use_Multiple_Sinks_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Makefile.Use_Ostream.am
+noinst_PROGRAMS += Use_Ostream
+
+Use_Ostream_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+Use_Ostream_SOURCES = \
+ Use_Ostream.cpp \
+ Callback-2.h \
+ Callback-3.h \
+ Callback.h \
+ LogManager.h \
+ Log_Msg_Alt.h \
+ Trace.h
+
+Use_Ostream_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Makefile.Use_Stderr.am
+noinst_PROGRAMS += Use_Stderr
+
+Use_Stderr_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+Use_Stderr_SOURCES = \
+ Use_Stderr.cpp \
+ Callback-2.h \
+ Callback-3.h \
+ Callback.h \
+ LogManager.h \
+ Log_Msg_Alt.h \
+ Trace.h
+
+Use_Stderr_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Makefile.Use_Syslog.am
+noinst_PROGRAMS += Use_Syslog
+
+Use_Syslog_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+Use_Syslog_SOURCES = \
+ Use_Syslog.cpp \
+ Callback-2.h \
+ Callback-3.h \
+ Callback.h \
+ LogManager.h \
+ Log_Msg_Alt.h \
+ Trace.h
+
+Use_Syslog_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Makefile.Wrap_Macros.am
+noinst_PROGRAMS += Wrap_Macros
+
+Wrap_Macros_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+Wrap_Macros_SOURCES = \
+ Wrap_Macros.cpp \
+ Callback-2.h \
+ Callback-3.h \
+ Callback.h \
+ LogManager.h \
+ Log_Msg_Alt.h \
+ Trace.h
+
+Wrap_Macros_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Makefile.Wrap_Macros_Alt.am
+noinst_PROGRAMS += Wrap_Macros_Alt
+
+Wrap_Macros_Alt_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+Wrap_Macros_Alt_SOURCES = \
+ Wrap_Macros_Alt.cpp \
+ Callback-2.h \
+ Callback-3.h \
+ Callback.h \
+ LogManager.h \
+ Log_Msg_Alt.h \
+ Trace.h
+
+Wrap_Macros_Alt_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Clean up template repositories, etc.
+clean-local:
+ -rm -f *~ *.bak *.rpo *.sym lib*.*_pure_* core core.*
+ -rm -f gcctemp.c gcctemp so_locations *.ics
+ -rm -rf cxx_repository ptrepository ti_files
+ -rm -rf templateregistry ir.out
+ -rm -rf ptrepository SunWS_cache Templates.DB
diff --git a/ACE/examples/APG/Logging/Simple1.cpp b/ACE/examples/APG/Logging/Simple1.cpp
new file mode 100644
index 00000000000..cf7a12e410b
--- /dev/null
+++ b/ACE/examples/APG/Logging/Simple1.cpp
@@ -0,0 +1,23 @@
+// $Id$
+
+#include "ace/Log_Msg.h"
+
+void foo (void);
+
+int ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ ACE_TRACE("main");
+
+ ACE_DEBUG ((LM_INFO, ACE_TEXT ("%IHi Mom\n")));
+ foo();
+ ACE_DEBUG ((LM_INFO, ACE_TEXT ("%IGoodnight\n")));
+
+ return 0;
+}
+
+void foo (void)
+{
+ ACE_TRACE ("foo");
+
+ ACE_DEBUG ((LM_INFO, ACE_TEXT ("%IHowdy Pardner\n")));
+}
diff --git a/ACE/examples/APG/Logging/Simple2.cpp b/ACE/examples/APG/Logging/Simple2.cpp
new file mode 100644
index 00000000000..26315b9d689
--- /dev/null
+++ b/ACE/examples/APG/Logging/Simple2.cpp
@@ -0,0 +1,25 @@
+// $Id$
+
+#include "ace/Log_Msg.h"
+
+void foo(void);
+
+int ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ ACE_TRACE ("main");
+
+ ACE_LOG_MSG->priority_mask (LM_DEBUG | LM_NOTICE,
+ ACE_Log_Msg::PROCESS);
+ ACE_DEBUG ((LM_INFO, ACE_TEXT ("%IHi Mom\n")));
+ foo ();
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("%IGoodnight\n")));
+
+ return 0;
+}
+
+void foo(void)
+{
+ ACE_TRACE ("foo");
+
+ ACE_DEBUG ((LM_NOTICE, ACE_TEXT ("%IHowdy Pardner\n")));
+}
diff --git a/ACE/examples/APG/Logging/Trace.h b/ACE/examples/APG/Logging/Trace.h
new file mode 100644
index 00000000000..c7f40c343eb
--- /dev/null
+++ b/ACE/examples/APG/Logging/Trace.h
@@ -0,0 +1,153 @@
+// $Id$
+
+#ifndef TRACE_H
+#define TRACE_H
+
+#include "ace/Log_Msg.h"
+
+// Listing 1 code/ch03
+class Trace
+{
+public:
+ Trace (const ACE_TCHAR *prefix,
+ const ACE_TCHAR *name,
+ int line,
+ const ACE_TCHAR *file)
+ {
+ this->prefix_ = prefix;
+ this->name_ = name;
+ this->line_ = line;
+ this->file_ = file;
+
+ ACE_Log_Msg *lm = ACE_LOG_MSG;
+ if (lm->tracing_enabled ()
+ && lm->trace_active () == 0)
+ {
+ lm->trace_active (1);
+ ACE_DEBUG
+ ((LM_TRACE,
+ ACE_TEXT ("%s%*s(%t) calling %s in file `%s'")
+ ACE_TEXT (" on line %d\n"),
+ this->prefix_,
+ Trace::nesting_indent_ * lm->inc (),
+ ACE_TEXT (""),
+ this->name_,
+ this->file_,
+ this->line_));
+ lm->trace_active (0);
+ }
+ }
+
+ void setLine (int line)
+ {
+ this->line_ = line;
+ }
+
+ ~Trace (void)
+ {
+ ACE_Log_Msg *lm = ACE_LOG_MSG;
+ if (lm->tracing_enabled ()
+ && lm->trace_active () == 0)
+ {
+ lm->trace_active (1);
+ ACE_DEBUG
+ ((LM_TRACE,
+ ACE_TEXT ("%s%*s(%t) leaving %s in file `%s'")
+ ACE_TEXT (" on line %d\n"),
+ this->prefix_,
+ Trace::nesting_indent_ * lm->dec (),
+ ACE_TEXT (""),
+ this->name_,
+ this->file_,
+ this->line_));
+ lm->trace_active (0);
+ }
+ }
+
+private:
+ enum { nesting_indent_ = 3 };
+
+ const ACE_TCHAR *prefix_;
+ const ACE_TCHAR *name_;
+ const ACE_TCHAR *file_;
+ int line_;
+};
+// Listing 1
+
+// Listing 2 code/ch03
+#define TRACE_PREFIX ACE_TEXT ("TRACE ")
+
+#if (ACE_NTRACE == 1)
+# define TRACE(X)
+# define TRACE_RETURN(V) return V;
+# define TRACE_RETURN_VOID()
+#else
+# define TRACE(X) \
+ Trace ____ (TRACE_PREFIX, \
+ ACE_TEXT (X), \
+ __LINE__, \
+ ACE_TEXT (__FILE__))
+
+# define TRACE_RETURN(V) \
+ do { ____.setLine(__LINE__); return V; } while (0)
+
+# define TRACE_RETURN_VOID() \
+ do { ____.setLine(__LINE__); } while (0)
+#endif
+// Listing 2
+
+//////////////////////////////////////////////////
+
+#if defined (__GNUC__) && (__GNUC__ >= 3 || __GNUC_MINOR__ > 95) && \
+ (!defined (VXWORKS) || !(__GNUC__ == 2 && __GNUC_MINOR__ == 96))
+// This stuff only works with g++ 2.96 and later...
+// But not with VxWorks g++ 2.96.
+
+// Listing 3 code/ch03
+
+#define DEBUG_PREFIX ACE_TEXT ("DEBUG%I")
+#define INFO_PREFIX ACE_TEXT ("INFO%I")
+#define NOTICE_PREFIX ACE_TEXT ("NOTICE%I")
+#define WARNING_PREFIX ACE_TEXT ("WARNING%I")
+#define ERROR_PREFIX ACE_TEXT ("ERROR%I")
+#define CRITICAL_PREFIX ACE_TEXT ("CRITICAL%I")
+#define ALERT_PREFIX ACE_TEXT ("ALERT%I")
+#define EMERGENCY_PREFIX ACE_TEXT ("EMERGENCY%I")
+
+#define MY_DEBUG(FMT, ...) \
+ ACE_DEBUG(( LM_DEBUG, \
+ DEBUG_PREFIX FMT \
+ ##__VA_ARGS__))
+#define MY_INFO(FMT, ...) \
+ ACE_DEBUG(( LM_INFO, \
+ INFO_PREFIX FMT \
+ ##__VA_ARGS__))
+#define MY_NOTICE(FMT, ...) \
+ ACE_DEBUG(( LM_NOTICE, \
+ NOTICE_PREFIX FMT \
+ ##__VA_ARGS__))
+#define MY_WARNING(FMT, ...) \
+ ACE_DEBUG(( LM_WARNING, \
+ WARNING_PREFIX FMT \
+ ##__VA_ARGS__))
+#define MY_ERROR(FMT, ...) \
+ ACE_DEBUG(( LM_ERROR, \
+ ERROR_PREFIX FMT \
+ ##__VA_ARGS__))
+#define MY_CRITICAL(FMT, ...) \
+ ACE_DEBUG(( LM_CRITICAL, \
+ CRITICAL_PREFIX FMT \
+ ##__VA_ARGS__))
+#define MY_ALERT(FMT, ...) \
+ ACE_DEBUG(( LM_ALERT, \
+ ALERT_PREFIX FMT \
+ ##__VA_ARGS__))
+#define MY_EMERGENCY(FMT, ...) \
+ ACE_DEBUG(( LM_EMERGENCY, \
+ EMERGENCY_PREFIX FMT \
+ ##__VA_ARGS__))
+// Listing 3
+
+#endif /* __GNUC__ */
+
+#endif /* TRACE_H */
diff --git a/ACE/examples/APG/Logging/Trace_Return.cpp b/ACE/examples/APG/Logging/Trace_Return.cpp
new file mode 100644
index 00000000000..1bb32a03456
--- /dev/null
+++ b/ACE/examples/APG/Logging/Trace_Return.cpp
@@ -0,0 +1,41 @@
+// $Id$
+
+#include "Trace.h"
+
+#if defined (__GNUC__) && (__GNUC__ >= 3 || __GNUC_MINOR__ > 95) && \
+ (!defined (VXWORKS) || !(__GNUC__ == 2 && __GNUC_MINOR__ == 96))
+// The DEBUG stuff only works with g++ 2.96 and later.
+// But not with VxWorks g++ 2.96.
+
+// Listing 1 code/ch03
+void foo (void);
+
+int ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ TRACE ("main");
+
+ MY_DEBUG (ACE_TEXT ("Hi Mom\n"));
+ foo ();
+ MY_DEBUG (ACE_TEXT ("Goodnight\n"));
+
+ TRACE_RETURN (0);
+}
+
+void foo (void)
+{
+ TRACE ("foo");
+ MY_DEBUG (ACE_TEXT ("Howdy Pardner\n"));
+ TRACE_RETURN_VOID ();
+}
+// Listing 1
+
+#else
+#include <stdio.h>
+
+int ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ puts ("This example only works on g++ 2.96 and later.\n");
+ return 0;
+}
+
+#endif /* __GNUC__ */
diff --git a/ACE/examples/APG/Logging/Use_Callback.cpp b/ACE/examples/APG/Logging/Use_Callback.cpp
new file mode 100644
index 00000000000..2f08a2127ed
--- /dev/null
+++ b/ACE/examples/APG/Logging/Use_Callback.cpp
@@ -0,0 +1,20 @@
+// $Id$
+
+#include "ace/Log_Msg.h"
+#include "Callback.h"
+
+int ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ Callback *callback = new Callback;
+
+ ACE_LOG_MSG->set_flags (ACE_Log_Msg::MSG_CALLBACK);
+ ACE_LOG_MSG->clr_flags (ACE_Log_Msg::STDERR);
+ ACE_LOG_MSG->msg_callback (callback);
+
+ ACE_TRACE ("main");
+
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("%IHi Mom\n")));
+ ACE_DEBUG ((LM_INFO, ACE_TEXT ("%IGoodnight\n")));
+
+ return 0;
+}
diff --git a/ACE/examples/APG/Logging/Use_Callback2.cpp b/ACE/examples/APG/Logging/Use_Callback2.cpp
new file mode 100644
index 00000000000..bcfe8b8e5d7
--- /dev/null
+++ b/ACE/examples/APG/Logging/Use_Callback2.cpp
@@ -0,0 +1,20 @@
+// $Id$
+
+#include "ace/Log_Msg.h"
+#include "Callback-2.h"
+
+int ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ Callback *callback = new Callback;
+
+ ACE_LOG_MSG->set_flags (ACE_Log_Msg::MSG_CALLBACK);
+ ACE_LOG_MSG->clr_flags (ACE_Log_Msg::STDERR);
+ ACE_LOG_MSG->msg_callback (callback);
+
+ ACE_TRACE ("main");
+
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("%IHi Mom\n")));
+ ACE_DEBUG ((LM_INFO, ACE_TEXT ("%IGoodnight\n")));
+
+ return 0;
+}
diff --git a/ACE/examples/APG/Logging/Use_LogManager.cpp b/ACE/examples/APG/Logging/Use_LogManager.cpp
new file mode 100644
index 00000000000..76de7b7fb56
--- /dev/null
+++ b/ACE/examples/APG/Logging/Use_LogManager.cpp
@@ -0,0 +1,33 @@
+// $Id$
+
+#include "LogManager.h"
+
+// Listing 1 code/ch03
+void foo (void);
+
+int ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ LOG_MANAGER->redirectToStderr ();
+ ACE_TRACE ("main");
+ LOG_MANAGER->redirectToSyslog ();
+ ACE_DEBUG ((LM_INFO, ACE_TEXT ("%IHi Mom\n")));
+ foo ();
+ LOG_MANAGER->redirectToDaemon ();
+ ACE_DEBUG ((LM_INFO, ACE_TEXT ("%IGoodnight\n")));
+
+ return 0;
+}
+void foo (void)
+{
+ ACE_TRACE ("foo");
+ LOG_MANAGER->redirectToFile ("output.test");
+ ACE_DEBUG ((LM_INFO, ACE_TEXT ("%IHowdy Pardner\n")));
+}
+// Listing 1
+
+// Listing 2 code/ch03
+#if defined (ACE_HAS_EXPLICIT_STATIC_TEMPLATE_MEMBER_INSTANTIATION)
+template ACE_Singleton<LogManager, ACE_Null_Mutex> *
+ ACE_Singleton<LogManager, ACE_Null_Mutex>::singleton_;
+#endif /* ACE_HAS_EXPLICIT_STATIC_TEMPLATE_MEMBER_INSTANTIATION */
+// Listing 2
diff --git a/ACE/examples/APG/Logging/Use_Logger.cpp b/ACE/examples/APG/Logging/Use_Logger.cpp
new file mode 100644
index 00000000000..5fb672c1ab4
--- /dev/null
+++ b/ACE/examples/APG/Logging/Use_Logger.cpp
@@ -0,0 +1,17 @@
+// $Id$
+
+#include "ace/Log_Msg.h"
+
+int ACE_TMAIN (int, ACE_TCHAR *argv[])
+{
+ ACE_LOG_MSG->open (argv[0],
+ ACE_Log_Msg::LOGGER,
+ ACE_DEFAULT_LOGGER_KEY);
+
+ ACE_TRACE ("main");
+
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("%IHi Mom\n")));
+ ACE_DEBUG ((LM_INFO, ACE_TEXT ("%IGoodnight\n")));
+
+ return 0;
+}
diff --git a/ACE/examples/APG/Logging/Use_Logging_Server.cpp b/ACE/examples/APG/Logging/Use_Logging_Server.cpp
new file mode 100644
index 00000000000..eaad6bf7a6b
--- /dev/null
+++ b/ACE/examples/APG/Logging/Use_Logging_Server.cpp
@@ -0,0 +1,20 @@
+// $Id$
+
+#include "ace/Log_Msg.h"
+#include "Callback-3.h"
+
+int ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ Callback *callback = new Callback;
+
+ ACE_LOG_MSG->set_flags (ACE_Log_Msg::MSG_CALLBACK);
+ ACE_LOG_MSG->clr_flags (ACE_Log_Msg::STDERR);
+ ACE_LOG_MSG->msg_callback (callback);
+
+ ACE_TRACE ("main");
+
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("%IHi Mom\n")));
+ ACE_DEBUG ((LM_INFO, ACE_TEXT ("%IGoodnight\n")));
+
+ return 0;
+}
diff --git a/ACE/examples/APG/Logging/Use_Logging_Strategy.cpp b/ACE/examples/APG/Logging/Use_Logging_Strategy.cpp
new file mode 100644
index 00000000000..559d85d65ae
--- /dev/null
+++ b/ACE/examples/APG/Logging/Use_Logging_Strategy.cpp
@@ -0,0 +1,33 @@
+// $Id$
+
+#include "ace/Log_Msg.h"
+#include "ace/Service_Config.h"
+
+/*
+ Put the following in your svc.conf:
+
+ dynamic Logger Service_Object * ACE:_make_ACE_Logging_Strategy() "-s log.out -f STDERR|OSTREAM -p DEBUG|NOTICE"
+
+ There seems to be a bug in ACE_Logging_Strategy in that the priority
+ flags are not propagated to spawned threads.
+*/
+
+// Listing 1 code/ch03
+int ACE_TMAIN (int argc, ACE_TCHAR *argv[])
+{
+ if (ACE_Service_Config::open (argc,
+ argv,
+ ACE_DEFAULT_LOGGER_KEY,
+ 1,
+ 0,
+ 1) < 0)
+ ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("%p\n"),
+ ACE_TEXT ("Service Config open")),
+ 1);
+ ACE_TRACE ("main");
+ ACE_DEBUG ((LM_NOTICE, ACE_TEXT ("%t%IHowdy Pardner\n")));
+ ACE_DEBUG ((LM_INFO, ACE_TEXT ("%t%IGoodnight\n")));
+
+ return 0;
+}
+// Listing 1
diff --git a/ACE/examples/APG/Logging/Use_Multiple_Sinks.cpp b/ACE/examples/APG/Logging/Use_Multiple_Sinks.cpp
new file mode 100644
index 00000000000..352a598b4e2
--- /dev/null
+++ b/ACE/examples/APG/Logging/Use_Multiple_Sinks.cpp
@@ -0,0 +1,34 @@
+// $Id$
+
+#include "ace/Log_Msg.h"
+#include "ace/streams.h"
+
+int ACE_TMAIN (int, ACE_TCHAR *argv[])
+{
+ // Output to default destination (stderr)
+ ACE_LOG_MSG->open (argv[0]);
+
+ ACE_TRACE ("main");
+
+ ACE_OSTREAM_TYPE *output =
+ (ACE_OSTREAM_TYPE *) new ofstream ("ostream.output.test");
+
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("%IThis will go to STDERR\n")));
+
+ ACE_LOG_MSG->open
+ (argv[0], ACE_Log_Msg::SYSLOG, ACE_TEXT ("syslogTest"));
+ ACE_LOG_MSG->set_flags (ACE_Log_Msg::STDERR);
+ ACE_DEBUG
+ ((LM_DEBUG, ACE_TEXT ("%IThis goes to STDERR & syslog\n")));
+
+ ACE_LOG_MSG->msg_ostream (output, 0);
+ ACE_LOG_MSG->set_flags (ACE_Log_Msg::OSTREAM);
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("%IThis will go to STDERR, ")
+ ACE_TEXT ("syslog & an ostream\n")));
+
+ ACE_LOG_MSG->clr_flags (ACE_Log_Msg::OSTREAM);
+ delete output;
+
+ return 0;
+}
diff --git a/ACE/examples/APG/Logging/Use_Ostream.cpp b/ACE/examples/APG/Logging/Use_Ostream.cpp
new file mode 100644
index 00000000000..28a2fefcc1c
--- /dev/null
+++ b/ACE/examples/APG/Logging/Use_Ostream.cpp
@@ -0,0 +1,36 @@
+// $Id$
+
+#include "ace/Log_Msg.h"
+#include "ace/streams.h"
+
+void foo (void);
+
+int ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ ACE_TRACE ("main");
+
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("%IHi Mom\n")));
+
+ /* Alternatively, you can use the set_flags() method to do the same
+ thing after the singleton has been created:
+ */
+ // Listing 2 code/ch03
+ ACE_OSTREAM_TYPE *output =
+ (ACE_OSTREAM_TYPE *) new ofstream ("ostream.output.test");
+ ACE_LOG_MSG->msg_ostream (output, 1);
+ ACE_LOG_MSG->set_flags (ACE_Log_Msg::OSTREAM);
+ ACE_LOG_MSG->clr_flags (ACE_Log_Msg::STDERR);
+ // Listing 2
+
+ foo ();
+ ACE_DEBUG ((LM_INFO, ACE_TEXT ("%IGoodnight\n")));
+
+ return 0;
+}
+
+void foo (void)
+{
+ ACE_TRACE ("foo");
+
+ ACE_DEBUG ((LM_INFO, ACE_TEXT ("%IHowdy Pardner\n")));
+}
diff --git a/ACE/examples/APG/Logging/Use_Stderr.cpp b/ACE/examples/APG/Logging/Use_Stderr.cpp
new file mode 100644
index 00000000000..e0418c4d362
--- /dev/null
+++ b/ACE/examples/APG/Logging/Use_Stderr.cpp
@@ -0,0 +1,38 @@
+// $Id$
+
+#include "ace/Log_Msg.h"
+
+void foo (void);
+
+// Listing 1 code/ch03
+int ACE_TMAIN (int, ACE_TCHAR *argv[])
+{
+ // open() requires the name of the application
+ // (e.g. -- argv[0]) because the underlying
+ // implementation may use it in the log output.
+ ACE_LOG_MSG->open (argv[0], ACE_Log_Msg::STDERR);
+ // Listing 1
+
+ /* Alternatively, you can use the set_flags() method to do the same
+ thing after the singleton has been created:
+ */
+
+ ACE_TRACE ("main");
+
+ // Listing 2 code/ch03
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("%IHi Mom\n")));
+ ACE_LOG_MSG->set_flags (ACE_Log_Msg::STDERR);
+ foo ();
+ // Listing 2
+
+ ACE_DEBUG ((LM_INFO, ACE_TEXT ("%IGoodnight\n")));
+
+ return 0;
+}
+
+void foo (void)
+{
+ ACE_TRACE ("foo");
+
+ ACE_DEBUG ((LM_INFO, ACE_TEXT ("%IHowdy Pardner\n")));
+}
diff --git a/ACE/examples/APG/Logging/Use_Syslog.cpp b/ACE/examples/APG/Logging/Use_Syslog.cpp
new file mode 100644
index 00000000000..dce4a1fe6b0
--- /dev/null
+++ b/ACE/examples/APG/Logging/Use_Syslog.cpp
@@ -0,0 +1,32 @@
+// $Id$
+
+#include "ace/Log_Msg.h"
+
+void foo (void);
+
+int ACE_TMAIN (int, ACE_TCHAR *argv[])
+{
+ // This will be directed to stderr (the default ACE_Log_Msg
+ // behavior).
+ ACE_TRACE ("main");
+
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("%IHi Mom\n")));
+
+ // Everything from foo() will be directed to the system logger
+ ACE_LOG_MSG->open
+ (argv[0], ACE_Log_Msg::SYSLOG, ACE_TEXT ("syslogTest"));
+ foo ();
+
+ // Now we reset the log output to default (stderr)
+ ACE_LOG_MSG->open (argv[0]);
+ ACE_DEBUG ((LM_INFO, ACE_TEXT ("%IGoodnight\n")));
+
+ return 0;
+}
+
+void foo (void)
+{
+ ACE_TRACE ("foo");
+
+ ACE_DEBUG ((LM_INFO, ACE_TEXT ("%IHowdy Pardner\n")));
+}
diff --git a/ACE/examples/APG/Logging/Wrap_Macros.cpp b/ACE/examples/APG/Logging/Wrap_Macros.cpp
new file mode 100644
index 00000000000..9e88d3e11e0
--- /dev/null
+++ b/ACE/examples/APG/Logging/Wrap_Macros.cpp
@@ -0,0 +1,38 @@
+// $Id$
+
+#include "Trace.h"
+
+#if defined (__GNUC__) && (__GNUC__ >= 3 || __GNUC_MINOR__ > 95) && \
+ (!defined (VXWORKS) || !(__GNUC__ == 2 && __GNUC_MINOR__ == 96))
+// The macros in Trace.h only work on g++ 2.96 and later.
+// But not with VxWorks g++ 2.96.
+
+// Listing 1 code/ch03
+void foo (void);
+
+int ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ ACE_TRACE ("main");
+ MY_DEBUG (ACE_TEXT ("Hi Mom\n"));
+ foo ();
+ MY_DEBUG (ACE_TEXT ("Goodnight\n"));
+ return 0;
+}
+
+void foo (void)
+{
+ ACE_TRACE ("foo");
+ MY_DEBUG (ACE_TEXT ("Howdy Pardner\n"));
+}
+// Listing 1
+
+#else
+#include <stdio.h>
+
+int ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ puts ("This example only works on g++ 2.96 and later.\n");
+ return 0;
+}
+
+#endif /* __GNUC__ */
diff --git a/ACE/examples/APG/Logging/Wrap_Macros_Alt.cpp b/ACE/examples/APG/Logging/Wrap_Macros_Alt.cpp
new file mode 100644
index 00000000000..306eefcd83a
--- /dev/null
+++ b/ACE/examples/APG/Logging/Wrap_Macros_Alt.cpp
@@ -0,0 +1,18 @@
+// $Id$
+
+#include "Log_Msg_Alt.h"
+
+void foo (void);
+
+int ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ ACE_TRACE ("main");
+
+ // Listing 1 code/ch03
+ ACE_DEBUG ((MY_DEBUG ACE_TEXT ("Hi Mom\n")));
+
+ ACE_DEBUG ((MY_DEBUG ACE_TEXT ("Goodnight\n")));
+ // Listing 1
+
+ return 0;
+}
diff --git a/ACE/examples/APG/Logging/client.conf b/ACE/examples/APG/Logging/client.conf
new file mode 100644
index 00000000000..1007e3aa7f6
--- /dev/null
+++ b/ACE/examples/APG/Logging/client.conf
@@ -0,0 +1 @@
+dynamic Client_Logging_Service Service_Object * netsvcs:_make_ACE_Client_Logging_Acceptor() active "-p 20009 -h localhost"
diff --git a/ACE/examples/APG/Logging/logging.mpc b/ACE/examples/APG/Logging/logging.mpc
new file mode 100644
index 00000000000..d40c2ae2704
--- /dev/null
+++ b/ACE/examples/APG/Logging/logging.mpc
@@ -0,0 +1,128 @@
+// -*- MPC -*-
+// $Id$
+
+project(Simple1) : aceexe {
+ exename = Simple1
+ Source_Files {
+ Simple1.cpp
+ }
+}
+
+project(Simple2) : aceexe {
+ exename = Simple2
+ Source_Files {
+ Simple2.cpp
+ }
+}
+
+project(Change Mask) : aceexe {
+ exename = Change_Mask
+ Source_Files {
+ Change_Mask.cpp
+ }
+}
+
+project(Change Instance Default) : aceexe {
+ exename = Change_Instance_Default
+ Source_Files {
+ Change_Instance_Default.cpp
+ }
+}
+
+project(Wrap Macros) : aceexe {
+ exename = Wrap_Macros
+ Source_Files {
+ Wrap_Macros.cpp
+ }
+}
+
+project(Wrap Macros Alt) : aceexe {
+ exename = Wrap_Macros_Alt
+ Source_Files {
+ Wrap_Macros_Alt.cpp
+ }
+}
+
+project(Trace Return) : aceexe {
+ exename = Trace_Return
+ Source_Files {
+ Trace_Return.cpp
+ }
+}
+
+project(Use Stderr) : aceexe {
+ exename = Use_Stderr
+ Source_Files {
+ Use_Stderr.cpp
+ }
+}
+
+project(Howto Syslog) : aceexe {
+ exename = Howto_Syslog
+ Source_Files {
+ Howto_Syslog.cpp
+ }
+}
+
+project(Use Syslog) : aceexe {
+ exename = Use_Syslog
+ Source_Files {
+ Use_Syslog.cpp
+ }
+}
+
+project(Use Ostream) : aceexe {
+ exename = Use_Ostream
+ Source_Files {
+ Use_Ostream.cpp
+ }
+}
+
+project(Use Multiple Sinks) : aceexe {
+ exename = Use_Multiple_Sinks
+ Source_Files {
+ Use_Multiple_Sinks.cpp
+ }
+}
+
+project(Use Callback) : aceexe {
+ exename = Use_Callback
+ Source_Files {
+ Use_Callback.cpp
+ }
+}
+
+project(Use Callback2) : aceexe {
+ exename = Use_Callback2
+ Source_Files {
+ Use_Callback2.cpp
+ }
+}
+
+project(Use Logger) : aceexe {
+ exename = Use_Logger
+ Source_Files {
+ Use_Logger.cpp
+ }
+}
+
+project(Use Logging Server) : aceexe {
+ exename = Use_Logging_Server
+ Source_Files {
+ Use_Logging_Server.cpp
+ }
+}
+
+project(Use LogManager) : aceexe {
+ exename = Use_LogManager
+ Source_Files {
+ Use_LogManager.cpp
+ }
+}
+
+project(Use Logging Strategy) : aceexe {
+ exename = Use_Logging_Strategy
+ Source_Files {
+ Use_Logging_Strategy.cpp
+ }
+}
diff --git a/ACE/examples/APG/Logging/logging_strategy.conf b/ACE/examples/APG/Logging/logging_strategy.conf
new file mode 100644
index 00000000000..b63501ee185
--- /dev/null
+++ b/ACE/examples/APG/Logging/logging_strategy.conf
@@ -0,0 +1 @@
+dynamic Logger Service_Object * ACE:_make_ACE_Logging_Strategy() "-s log.out -f STDERR|OSTREAM -p INFO"
diff --git a/ACE/examples/APG/Logging/server.conf b/ACE/examples/APG/Logging/server.conf
new file mode 100644
index 00000000000..31f8fd95d9d
--- /dev/null
+++ b/ACE/examples/APG/Logging/server.conf
@@ -0,0 +1,3 @@
+dynamic Logger Service_Object * ACE:_make_ACE_Logging_Strategy() "-s foobar -f STDERR|OSTREAM|VERBOSE"
+
+dynamic Server_Logging_Service Service_Object * netsvcs:_make_ACE_Server_Logging_Acceptor() active "-p 20009"
diff --git a/ACE/examples/APG/Makefile.am b/ACE/examples/APG/Makefile.am
new file mode 100644
index 00000000000..f79765c9348
--- /dev/null
+++ b/ACE/examples/APG/Makefile.am
@@ -0,0 +1,31 @@
+## Process this file with automake to create Makefile.in
+##
+## $Id$
+##
+## This file was generated by MPC. Any changes made directly to
+## this file will be lost the next time it is generated.
+##
+## MPC Command:
+## /acebuilds/ACE_wrappers-repository/bin/mwc.pl -include /acebuilds/MPC/config -include /acebuilds/MPC/templates -feature_file /acebuilds/ACE_wrappers-repository/local.features -noreldefs -type automake -exclude build,Kokyu
+
+SUBDIRS = \
+ Active_Objects \
+ Config \
+ Containers \
+ Logging \
+ Misc_IPC \
+ Naming \
+ Proactor \
+ Processes \
+ Reactor \
+ Shared_Memory \
+ Signals \
+ Sockets \
+ Streams \
+ Svc_Config \
+ ThreadManagement \
+ ThreadPools \
+ ThreadSafety \
+ Threads \
+ Timers
+
diff --git a/ACE/examples/APG/Misc_IPC/.cvsignore b/ACE/examples/APG/Misc_IPC/.cvsignore
new file mode 100644
index 00000000000..155f8a18824
--- /dev/null
+++ b/ACE/examples/APG/Misc_IPC/.cvsignore
@@ -0,0 +1,6 @@
+UDP_Broadcast
+UDP_Broadcast
+UDP_Multicast
+UDP_Multicast
+UDP_Unicast
+UDP_Unicast
diff --git a/ACE/examples/APG/Misc_IPC/Makefile.am b/ACE/examples/APG/Misc_IPC/Makefile.am
new file mode 100644
index 00000000000..656f63fb00c
--- /dev/null
+++ b/ACE/examples/APG/Misc_IPC/Makefile.am
@@ -0,0 +1,69 @@
+## Process this file with automake to create Makefile.in
+##
+## $Id$
+##
+## This file was generated by MPC. Any changes made directly to
+## this file will be lost the next time it is generated.
+##
+## MPC Command:
+## /acebuilds/ACE_wrappers-repository/bin/mwc.pl -include /acebuilds/MPC/config -include /acebuilds/MPC/templates -feature_file /acebuilds/ACE_wrappers-repository/local.features -noreldefs -type automake -exclude build,Kokyu
+
+ACE_BUILDDIR = $(top_builddir)
+ACE_ROOT = $(top_srcdir)
+
+noinst_PROGRAMS =
+
+## Makefile.UDP_Broadcast.am
+
+if !BUILD_ACE_FOR_TAO
+noinst_PROGRAMS += UDP_Broadcast
+
+UDP_Broadcast_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+UDP_Broadcast_SOURCES = \
+ UDP_Broadcast.cpp
+
+UDP_Broadcast_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+endif !BUILD_ACE_FOR_TAO
+
+## Makefile.UDP_Multicast.am
+noinst_PROGRAMS += UDP_Multicast
+
+UDP_Multicast_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+UDP_Multicast_SOURCES = \
+ UDP_Multicast.cpp
+
+UDP_Multicast_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Makefile.UDP_Unicast.am
+
+if !BUILD_ACE_FOR_TAO
+noinst_PROGRAMS += UDP_Unicast
+
+UDP_Unicast_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+UDP_Unicast_SOURCES = \
+ UDP_Unicast.cpp
+
+UDP_Unicast_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+endif !BUILD_ACE_FOR_TAO
+
+## Clean up template repositories, etc.
+clean-local:
+ -rm -f *~ *.bak *.rpo *.sym lib*.*_pure_* core core.*
+ -rm -f gcctemp.c gcctemp so_locations *.ics
+ -rm -rf cxx_repository ptrepository ti_files
+ -rm -rf templateregistry ir.out
+ -rm -rf ptrepository SunWS_cache Templates.DB
diff --git a/ACE/examples/APG/Misc_IPC/UDP_Broadcast.cpp b/ACE/examples/APG/Misc_IPC/UDP_Broadcast.cpp
new file mode 100644
index 00000000000..318be67b19c
--- /dev/null
+++ b/ACE/examples/APG/Misc_IPC/UDP_Broadcast.cpp
@@ -0,0 +1,34 @@
+/**
+ * $Id$
+ *
+ * Sample code from The ACE Programmer's Guide,
+ * Copyright 2003 Addison-Wesley. All Rights Reserved.
+ */
+
+// Listing 1 code/ch09
+#include "ace/OS_NS_string.h"
+#include "ace/Log_Msg.h"
+#include "ace/INET_Addr.h"
+#include "ace/SOCK_Dgram_Bcast.h"
+
+int send_broadcast (u_short to_port)
+{
+ const char *message = "this is the message!\n";
+ ACE_INET_Addr my_addr (static_cast<u_short> (10101));
+ ACE_SOCK_Dgram_Bcast udp (my_addr);
+ ssize_t sent = udp.send (message,
+ ACE_OS::strlen (message) + 1,
+ to_port);
+ udp.close ();
+ if (sent == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("%p\n"),
+ ACE_TEXT ("send")), -1);
+ return 0;
+}
+// Listing 1
+
+int ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ send_broadcast (10);
+ return 0;
+}
diff --git a/ACE/examples/APG/Misc_IPC/UDP_Multicast.cpp b/ACE/examples/APG/Misc_IPC/UDP_Multicast.cpp
new file mode 100644
index 00000000000..feb2baafc57
--- /dev/null
+++ b/ACE/examples/APG/Misc_IPC/UDP_Multicast.cpp
@@ -0,0 +1,37 @@
+/**
+ * $Id$
+ *
+ * Sample code from The ACE Programmer's Guide,
+ * Copyright 2003 Addison-Wesley. All Rights Reserved.
+ */
+
+// Listing 1 code/ch09
+#include "ace/OS_NS_string.h"
+#include "ace/Log_Msg.h"
+#include "ace/INET_Addr.h"
+#include "ace/SOCK_Dgram_Mcast.h"
+
+int send_multicast (const ACE_INET_Addr &mcast_addr)
+{
+ const char *message = "this is the message!\n";
+ ACE_SOCK_Dgram_Mcast udp;
+ if (-1 == udp.join (mcast_addr))
+ ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("%p\n"),
+ ACE_TEXT ("join")), -1);
+
+ ssize_t sent = udp.send (message,
+ ACE_OS::strlen (message) + 1);
+ udp.close ();
+ if (sent == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("%p\n"),
+ ACE_TEXT ("send")), -1);
+ return 0;
+}
+// Listing 1
+
+int ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ ACE_INET_Addr nop;
+ send_multicast (nop);
+ return 0;
+}
diff --git a/ACE/examples/APG/Misc_IPC/UDP_Unicast.cpp b/ACE/examples/APG/Misc_IPC/UDP_Unicast.cpp
new file mode 100644
index 00000000000..ac3d4d00488
--- /dev/null
+++ b/ACE/examples/APG/Misc_IPC/UDP_Unicast.cpp
@@ -0,0 +1,71 @@
+/**
+ * $Id$
+ *
+ * Sample code from The ACE Programmer's Guide,
+ * Copyright 2003 Addison-Wesley. All Rights Reserved.
+ */
+
+// Listing 1 code/ch09
+#include "ace/OS_NS_string.h"
+#include "ace/Log_Msg.h"
+#include "ace/INET_Addr.h"
+#include "ace/SOCK_Dgram.h"
+
+int send_unicast (const ACE_INET_Addr &to)
+{
+ const char *message = "this is the message!\n";
+ ACE_INET_Addr my_addr (static_cast<u_short> (10101));
+ ACE_SOCK_Dgram udp (my_addr);
+ ssize_t sent = udp.send (message,
+ ACE_OS::strlen (message) + 1,
+ to);
+ udp.close ();
+ if (sent == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("%p\n"),
+ ACE_TEXT ("send")), -1);
+ return 0;
+}
+// Listing 1
+
+// Listing 2 code/ch09
+void echo_dgram (void)
+{
+ ACE_INET_Addr my_addr (static_cast<u_short> (10102));
+ ACE_INET_Addr your_addr;
+ ACE_SOCK_Dgram udp (my_addr);
+ char buff[BUFSIZ];
+ size_t buflen = sizeof (buff);
+ ssize_t recv_cnt = udp.recv (buff, buflen, your_addr);
+ if (recv_cnt > 0)
+ udp.send (buff, static_cast<size_t> (buflen), your_addr);
+ udp.close ();
+ return;
+}
+// Listing 2
+
+// Listing 3 code/ch09
+#include "ace/SOCK_CODgram.h"
+// Exclude 3
+static void show_codgram (void)
+{
+ char buff[BUFSIZ];
+ size_t buflen = sizeof (buff);
+ // Exclude 3
+ const ACE_TCHAR *peer = ACE_TEXT ("other_host:8042");
+ ACE_INET_Addr peer_addr (peer);
+ ACE_SOCK_CODgram udp;
+ if (0 != udp.open (peer_addr))
+ ACE_ERROR ((LM_ERROR, ACE_TEXT ("%p\n"), peer));
+
+ // ...
+
+ if (-1 == udp.send (buff, buflen))
+ ACE_ERROR ((LM_ERROR, ACE_TEXT ("%p\n"), ACE_TEXT ("send")));
+ // Listing 3
+}
+
+int ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ show_codgram ();
+ return 0;
+}
diff --git a/ACE/examples/APG/Misc_IPC/misc_ipc.mpc b/ACE/examples/APG/Misc_IPC/misc_ipc.mpc
new file mode 100644
index 00000000000..47e1c34758b
--- /dev/null
+++ b/ACE/examples/APG/Misc_IPC/misc_ipc.mpc
@@ -0,0 +1,25 @@
+// -*- MPC -*-
+// $Id$
+
+project(UDP Broadcast) : aceexe {
+ avoids += ace_for_tao
+ exename = UDP_Broadcast
+ Source_Files {
+ UDP_Broadcast.cpp
+ }
+}
+
+project(UDP Multicast) : aceexe {
+ exename = UDP_Multicast
+ Source_Files {
+ UDP_Multicast.cpp
+ }
+}
+
+project(UDP Unicast) : aceexe {
+ avoids += ace_for_tao
+ exename = UDP_Unicast
+ Source_Files {
+ UDP_Unicast.cpp
+ }
+}
diff --git a/ACE/examples/APG/Naming/.cvsignore b/ACE/examples/APG/Naming/.cvsignore
new file mode 100644
index 00000000000..e5fd579f85d
--- /dev/null
+++ b/ACE/examples/APG/Naming/.cvsignore
@@ -0,0 +1,10 @@
+Netlocal
+Netlocal
+Netlocal_reader
+Netlocal_reader
+Nodelocal
+Nodelocal
+Nodelocal_shared
+Nodelocal_shared
+Nodelocal_shared_reader
+Nodelocal_shared_reader
diff --git a/ACE/examples/APG/Naming/EMail.h b/ACE/examples/APG/Naming/EMail.h
new file mode 100644
index 00000000000..fc38913a10a
--- /dev/null
+++ b/ACE/examples/APG/Naming/EMail.h
@@ -0,0 +1,28 @@
+// $Id$
+
+#ifndef EMAIL_H
+#define EMAIL_H
+
+#include "ace/Log_Msg.h"
+
+class EMail
+ {
+ public:
+ EMail()
+ { }
+
+ int send (const char *to,
+ const char *from,
+ const char *subject,
+ const char *message)
+ {
+ ACE_DEBUG ((LM_ERROR, ACE_TEXT ("To:\t%s\n"), to));
+ ACE_DEBUG ((LM_ERROR, ACE_TEXT ("From:\t%s\n"), from));
+ ACE_DEBUG ((LM_ERROR, ACE_TEXT ("Subject:\t%s\n"), subject));
+ ACE_DEBUG ((LM_ERROR, ACE_TEXT ("\n%s\n"), message));
+
+ return 0;
+ }
+ };
+
+#endif /* EMAIL_H */
diff --git a/ACE/examples/APG/Naming/Graph.cpp b/ACE/examples/APG/Naming/Graph.cpp
new file mode 100644
index 00000000000..62ca52afd0d
--- /dev/null
+++ b/ACE/examples/APG/Naming/Graph.cpp
@@ -0,0 +1,47 @@
+// $Id$
+
+#include "ace/Log_Msg.h"
+#include "Graph.h"
+
+void Graph::graph (char *filename, Graphable_Element_List &data)
+{
+ data.sort ();
+
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Save graph to %C\n"), filename));
+
+ char h[10][10];
+ for (int n = 0 ; n < 10 ; ++n )
+ {
+ for (int j = 0; j < 10; ++j )
+ {
+ h[n][j] = ' ';
+ }
+ }
+
+ int l[10];
+ int k = 0;
+ for (Graphable_Element_List::iterator i = data.begin ();
+ i != data.end ();
+ ++i, ++k )
+ {
+ l[k] = (*i).when ();
+
+ int temp = (int)((*i).temp () - 80.0);
+
+ for (int j = 0; j <= temp; ++j)
+ {
+ h[k][j] = '#';
+ }
+ }
+
+ for (int m = 0 ; m < 10 ; ++m)
+ {
+ ACE_DEBUG ((LM_INFO, ACE_TEXT ("%d "), l[m]));
+
+ for (int j = 0; j < 10; ++j)
+ {
+ ACE_DEBUG ((LM_INFO, ACE_TEXT ("%c"), h[m][j]));
+ }
+ ACE_DEBUG ((LM_INFO, ACE_TEXT ("\n")));
+ }
+}
diff --git a/ACE/examples/APG/Naming/Graph.h b/ACE/examples/APG/Naming/Graph.h
new file mode 100644
index 00000000000..135b7d14f77
--- /dev/null
+++ b/ACE/examples/APG/Naming/Graph.h
@@ -0,0 +1,18 @@
+// $Id$
+
+#ifndef GRAPH_H
+#define GRAPH_H
+
+#include "Graphable_Element.h"
+
+class Graph
+ {
+ public:
+ Graph()
+ {
+ }
+
+ void graph( char * filename, Graphable_Element_List & data );
+ };
+
+#endif /* GRAPH_H */
diff --git a/ACE/examples/APG/Naming/Graphable_Element.cpp b/ACE/examples/APG/Naming/Graphable_Element.cpp
new file mode 100644
index 00000000000..c3ff6ee7b41
--- /dev/null
+++ b/ACE/examples/APG/Naming/Graphable_Element.cpp
@@ -0,0 +1,4 @@
+// $Id$
+
+#include "Graphable_Element.h"
+
diff --git a/ACE/examples/APG/Naming/Graphable_Element.h b/ACE/examples/APG/Naming/Graphable_Element.h
new file mode 100644
index 00000000000..42758934993
--- /dev/null
+++ b/ACE/examples/APG/Naming/Graphable_Element.h
@@ -0,0 +1,53 @@
+/* -*- C++ -*- */
+// $Id$
+
+#ifndef GRAPHABLE_ELEMENT_H
+#define GRAPHABLE_ELEMENT_H
+
+#include "Name_Binding.h"
+#include <list>
+
+// A helper class that knows how to sort two ACE_Name_Binding objects
+// which contain temperature metrics. The value stored in the binding
+// is expected to be of the format "time|temp".
+//
+// Listing 1 code/ch21
+class Graphable_Element : public Name_Binding
+{
+public:
+ Graphable_Element (ACE_Name_Binding *entry)
+ : Name_Binding(entry)
+ {
+ sscanf (this->value (), "%d|%f", &this->when_, &this->temp_);
+ }
+ // Listing 1
+
+ // Listing 2 code/ch21
+ inline int when (void) const
+ {
+ return this->when_;
+ }
+
+ inline float temp (void)
+ {
+ return this->temp_;
+ }
+ // Listing 2
+
+ // Listing 3 code/ch21
+ inline bool operator< (const Graphable_Element &other) const
+ {
+ return this->when () < other.when ();
+ }
+ // Listing 3
+
+ // Listing 4 code/ch21
+private:
+ int when_;
+ float temp_;
+};
+
+typedef std::list<Graphable_Element> Graphable_Element_List;
+// Listing 4
+
+#endif /* GRAPHABLE_ELEMENT_H */
diff --git a/ACE/examples/APG/Naming/Makefile.am b/ACE/examples/APG/Naming/Makefile.am
new file mode 100644
index 00000000000..f73b1258348
--- /dev/null
+++ b/ACE/examples/APG/Naming/Makefile.am
@@ -0,0 +1,123 @@
+## Process this file with automake to create Makefile.in
+##
+## $Id$
+##
+## This file was generated by MPC. Any changes made directly to
+## this file will be lost the next time it is generated.
+##
+## MPC Command:
+## /acebuilds/ACE_wrappers-repository/bin/mwc.pl -include /acebuilds/MPC/config -include /acebuilds/MPC/templates -feature_file /acebuilds/ACE_wrappers-repository/local.features -noreldefs -type automake -exclude build,Kokyu
+
+ACE_BUILDDIR = $(top_builddir)
+ACE_ROOT = $(top_srcdir)
+
+noinst_PROGRAMS =
+
+## Makefile.Netlocal.am
+
+if !BUILD_ACE_FOR_TAO
+noinst_PROGRAMS += Netlocal
+
+Netlocal_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+Netlocal_SOURCES = \
+ Netlocal.cpp \
+ Temperature_Monitor2.cpp \
+ Temperature_Monitor2.h
+
+Netlocal_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+endif !BUILD_ACE_FOR_TAO
+
+## Makefile.Netlocal_Reader.am
+
+if !BUILD_ACE_FOR_TAO
+noinst_PROGRAMS += Netlocal_reader
+
+Netlocal_reader_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+Netlocal_reader_SOURCES = \
+ Graph.cpp \
+ Netlocal_reader.cpp \
+ Temperature_Grapher.cpp \
+ Graph.h \
+ Temperature_Grapher.h
+
+Netlocal_reader_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+endif !BUILD_ACE_FOR_TAO
+
+## Makefile.Nodelocal.am
+
+if !BUILD_ACE_FOR_TAO
+noinst_PROGRAMS += Nodelocal
+
+Nodelocal_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+Nodelocal_SOURCES = \
+ Nodelocal.cpp \
+ Temperature_Monitor.cpp \
+ Temperature_Monitor.h
+
+Nodelocal_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+endif !BUILD_ACE_FOR_TAO
+
+## Makefile.Nodelocal_Shared.am
+
+if !BUILD_ACE_FOR_TAO
+noinst_PROGRAMS += Nodelocal_shared
+
+Nodelocal_shared_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+Nodelocal_shared_SOURCES = \
+ Nodelocal_shared.cpp \
+ Temperature_Monitor2.cpp \
+ Temperature_Monitor2.h
+
+Nodelocal_shared_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+endif !BUILD_ACE_FOR_TAO
+
+## Makefile.Nodelocal_Shared_Reader.am
+
+if !BUILD_ACE_FOR_TAO
+noinst_PROGRAMS += Nodelocal_shared_reader
+
+Nodelocal_shared_reader_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+Nodelocal_shared_reader_SOURCES = \
+ Graph.cpp \
+ Nodelocal_shared_reader.cpp \
+ Temperature_Grapher.cpp \
+ Temperature_Monitor.cpp \
+ Graph.h \
+ Temperature_Grapher.h \
+ Temperature_Monitor.h
+
+Nodelocal_shared_reader_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+endif !BUILD_ACE_FOR_TAO
+
+## Clean up template repositories, etc.
+clean-local:
+ -rm -f *~ *.bak *.rpo *.sym lib*.*_pure_* core core.*
+ -rm -f gcctemp.c gcctemp so_locations *.ics
+ -rm -rf cxx_repository ptrepository ti_files
+ -rm -rf templateregistry ir.out
+ -rm -rf ptrepository SunWS_cache Templates.DB
diff --git a/ACE/examples/APG/Naming/Name_Binding.h b/ACE/examples/APG/Naming/Name_Binding.h
new file mode 100644
index 00000000000..6c093a941f2
--- /dev/null
+++ b/ACE/examples/APG/Naming/Name_Binding.h
@@ -0,0 +1,61 @@
+/* -*- C++ -*- */
+// $Id$
+
+#ifndef NAME_BINDING_H
+#define NAME_BINDING_H
+
+#include "ace/OS_NS_stdlib.h"
+#include "ace/OS_NS_string.h"
+#include "ace/Auto_Ptr.h"
+#include "ace/Name_Space.h"
+
+// Listing 1 code/ch21
+class Name_Binding
+{
+public:
+ Name_Binding (ACE_Name_Binding *entry)
+ {
+ this->name_ = entry->name_.char_rep ();
+ this->value_ = entry->value_.char_rep ();
+ this->type_ = ACE_OS::strdup (entry->type_);
+ }
+
+ Name_Binding (const ACE_NS_WString &n,
+ const ACE_NS_WString &v,
+ const char *t)
+ {
+ this->name_ = n.char_rep ();
+ this->value_ = v.char_rep ();
+ this->type_ = ACE_OS::strdup (t);
+ }
+
+ ~Name_Binding ()
+ {
+ delete this->name_;
+ delete this->value_;
+ ACE_OS::free (const_cast<char*> (this->type_));
+ this->type_ = 0;
+ }
+
+ char *name (void)
+ { return this->name_; }
+
+ char *value (void)
+ { return this->value_; }
+
+ const char *type (void)
+ { return this->type_; }
+
+ int int_value (void)
+ { return ACE_OS::atoi (this->value ()); }
+
+private:
+ char *name_;
+ char *value_;
+ char *type_;
+};
+
+typedef auto_ptr<Name_Binding> Name_Binding_Ptr;
+// Listing 1
+
+#endif /* NAME_BINDING_H */
diff --git a/ACE/examples/APG/Naming/Naming_Context.h b/ACE/examples/APG/Naming/Naming_Context.h
new file mode 100644
index 00000000000..abcf793b2b6
--- /dev/null
+++ b/ACE/examples/APG/Naming/Naming_Context.h
@@ -0,0 +1,68 @@
+/* -*- C++ -*- */
+// $Id$
+
+#ifndef NAMING_CONTEXT_H
+#define NAMING_CONTEXT_H
+
+#include "ace/Naming_Context.h"
+#include "ace/OS_NS_stdio.h"
+#include "Name_Binding.h"
+
+// Listing 1 code/ch21
+class Naming_Context : public ACE_Naming_Context
+{
+public:
+ typedef ACE_Naming_Context inherited;
+
+ int rebind (const char *name_in,
+ const char *value_in,
+ const char *type_in = "")
+ {
+ return this->inherited::rebind (name_in, value_in, type_in);
+ }
+
+ int rebind (const char *name_in,
+ float value_in,
+ const char *type_in = "")
+ {
+ char buf[BUFSIZ];
+ ACE_OS::sprintf (buf, "%2f", value_in);
+ return this->inherited::rebind (name_in,
+ (const char *)buf,
+ type_in);
+ }
+
+ int rebind (const char *name_in,
+ int value_in,
+ const char *type_in = "")
+ {
+ char buf[BUFSIZ];
+ ACE_OS::sprintf (buf, "%d", value_in );
+ return this->inherited::rebind (name_in,
+ (const char *)buf,
+ type_in);
+ }
+ // Listing 1
+
+ // Listing 2 code/ch21
+ Name_Binding *fetch (const char *name)
+ {
+ ACE_NS_WString value;
+ char *type;
+
+ if (this->resolve (name, value, type) != 0 ||
+ value.length () < 1)
+ {
+ return 0;
+ }
+
+ Name_Binding *rval =
+ new Name_Binding (ACE_NS_WString (name),
+ value,
+ type);
+ return rval;
+ }
+// Listing 2
+};
+
+#endif /* NAMING_CONTEXT_H */
diff --git a/ACE/examples/APG/Naming/Netlocal.cpp b/ACE/examples/APG/Naming/Netlocal.cpp
new file mode 100644
index 00000000000..f1799ab3882
--- /dev/null
+++ b/ACE/examples/APG/Naming/Netlocal.cpp
@@ -0,0 +1,40 @@
+// $Id$
+
+#include "Naming_Context.h"
+#include "Temperature_Monitor2.h"
+#include "Temperature_Monitor_Options.h"
+
+// Listing 1 code/ch21
+int ACE_TMAIN (int argc, ACE_TCHAR *argv[])
+{
+ Temperature_Monitor_Options opt (argc, argv);
+
+ Naming_Context process_context;
+ {
+ ACE_Name_Options *name_options =
+ process_context.name_options ();
+ name_options->context (ACE_Naming_Context::PROC_LOCAL);
+ ACE_TCHAR *nargv[] = { argv[0] };
+ name_options->parse_args (sizeof(nargv) / sizeof(ACE_TCHAR*),
+ nargv);
+ process_context.open (name_options->context ());
+ }
+
+ Naming_Context shared_context;
+ {
+ ACE_Name_Options *name_options =
+ shared_context.name_options ();
+ name_options->process_name (argv[0]);
+ name_options->context (ACE_Naming_Context::NET_LOCAL);
+ shared_context.open (name_options->context ());
+ }
+
+ Temperature_Monitor2 temperature_monitor (opt,
+ process_context,
+ shared_context);
+ temperature_monitor.monitor ();
+ process_context.close ();
+ shared_context.close ();
+ return 0;
+}
+// Listing 1
diff --git a/ACE/examples/APG/Naming/Netlocal_reader.cpp b/ACE/examples/APG/Naming/Netlocal_reader.cpp
new file mode 100644
index 00000000000..f77724aabbe
--- /dev/null
+++ b/ACE/examples/APG/Naming/Netlocal_reader.cpp
@@ -0,0 +1,23 @@
+// $Id$
+
+#include "Naming_Context.h"
+#include "Temperature_Grapher.h"
+#include "Temperature_Grapher_Options.h"
+
+// Listing 1 code/ch21
+int ACE_TMAIN (int argc, ACE_TCHAR *argv[])
+{
+ Temperature_Grapher_Options opt (argc, argv);
+
+ Naming_Context naming_context;
+ ACE_Name_Options *name_options = naming_context.name_options ();
+ name_options->process_name (argv[0]);
+ name_options->context (ACE_Naming_Context::NET_LOCAL);
+ naming_context.open (name_options->context ());
+
+ Temperature_Grapher grapher (opt, naming_context);
+ grapher.monitor ();
+ naming_context.close ();
+ return 0;
+}
+// Listing 1
diff --git a/ACE/examples/APG/Naming/Nodelocal.cpp b/ACE/examples/APG/Naming/Nodelocal.cpp
new file mode 100644
index 00000000000..ca37a27e374
--- /dev/null
+++ b/ACE/examples/APG/Naming/Nodelocal.cpp
@@ -0,0 +1,37 @@
+// $Id$
+
+#include "Naming_Context.h"
+#include "Temperature_Monitor.h"
+#include "Temperature_Monitor_Options.h"
+
+// Listing 1 code/ch21
+int ACE_TMAIN (int argc, ACE_TCHAR *argv[])
+{
+ Temperature_Monitor_Options opt (argc, argv);
+ // Listing 1
+
+ // Listing 2 code/ch21
+ Naming_Context naming_context;
+
+ ACE_Name_Options *name_options = naming_context.name_options();
+ // Listing 2
+
+ // Listing 3 code/ch21
+ ACE_TCHAR *naming_options_argv[] = { argv[0] };
+ name_options->parse_args
+ (sizeof(naming_options_argv) / sizeof(ACE_TCHAR*),
+ naming_options_argv);
+ name_options->context (ACE_Naming_Context::PROC_LOCAL);
+ naming_context.open (name_options->context ());
+ // Listing 3
+
+ // Listing 4 code/ch21
+ Temperature_Monitor temperature_monitor (opt, naming_context);
+ temperature_monitor.monitor ();
+ // Listing 4
+
+ // Listing 5 code/ch21
+ naming_context.close ();
+ return 0;
+ // Listing 5
+}
diff --git a/ACE/examples/APG/Naming/Nodelocal_shared.cpp b/ACE/examples/APG/Naming/Nodelocal_shared.cpp
new file mode 100644
index 00000000000..34ea87aab2d
--- /dev/null
+++ b/ACE/examples/APG/Naming/Nodelocal_shared.cpp
@@ -0,0 +1,43 @@
+// $Id$
+
+#include "Naming_Context.h"
+#include "Temperature_Monitor2.h"
+#include "Temperature_Monitor_Options.h"
+
+// Listing 1 code/ch21
+int ACE_TMAIN (int argc, ACE_TCHAR *argv[])
+{
+ Temperature_Monitor_Options opt (argc, argv);
+ Naming_Context process_context;
+ {
+ ACE_Name_Options *name_options =
+ process_context.name_options ();
+ name_options->context (ACE_Naming_Context::PROC_LOCAL);
+ ACE_TCHAR *nargv[] = { argv[0] };
+ name_options->parse_args (sizeof(nargv) / sizeof(ACE_TCHAR*) ,
+ nargv);
+ process_context.open (name_options->context ());
+ }
+
+ Naming_Context shared_context;
+ {
+ ACE_Name_Options *name_options =
+ shared_context.name_options ();
+ name_options->process_name (argv[0]);
+ name_options->context (ACE_Naming_Context::NODE_LOCAL);
+ shared_context.open (name_options->context ());
+ }
+
+ Temperature_Monitor2 temperature_monitor (opt,
+ process_context,
+ shared_context);
+ temperature_monitor.monitor ();
+
+ process_context.close ();
+ shared_context.close ();
+
+ return 0;
+}
+// Listing 1
+
+
diff --git a/ACE/examples/APG/Naming/Nodelocal_shared_reader.cpp b/ACE/examples/APG/Naming/Nodelocal_shared_reader.cpp
new file mode 100644
index 00000000000..7385f09a496
--- /dev/null
+++ b/ACE/examples/APG/Naming/Nodelocal_shared_reader.cpp
@@ -0,0 +1,23 @@
+// $Id$
+
+#include "Naming_Context.h"
+#include "Temperature_Grapher.h"
+#include "Temperature_Grapher_Options.h"
+
+// Listing 1 code/ch21
+int ACE_TMAIN (int argc, ACE_TCHAR *argv[])
+{
+ Temperature_Grapher_Options opt (argc, argv);
+
+ Naming_Context naming_context;
+ ACE_Name_Options *name_options = naming_context.name_options ();
+ name_options->process_name (argv[0]);
+ name_options->context (ACE_Naming_Context::NODE_LOCAL);
+ naming_context.open (name_options->context ());
+
+ Temperature_Grapher grapher (opt, naming_context);
+ grapher.monitor ();
+ naming_context.close ();
+ return 0;
+}
+// Listing 1
diff --git a/ACE/examples/APG/Naming/Temperature_Grapher.cpp b/ACE/examples/APG/Naming/Temperature_Grapher.cpp
new file mode 100644
index 00000000000..e11367af4a0
--- /dev/null
+++ b/ACE/examples/APG/Naming/Temperature_Grapher.cpp
@@ -0,0 +1,81 @@
+// $Id$
+
+#include "ace/OS_NS_unistd.h"
+#include "ace/Log_Msg.h"
+
+#include "Graph.h"
+#include "Graphable_Element.h"
+#include "Temperature_Grapher.h"
+
+// Listing 1 code/ch21
+void Temperature_Grapher::monitor (void)
+{
+ for (;;)
+ {
+ this->update_graph ();
+ ACE_OS::sleep (this->opt_.poll_interval ());
+ }
+}
+// Listing 1
+
+// Listing 2 code/ch21
+void Temperature_Grapher::update_graph (void)
+{
+ Name_Binding_Ptr lastUpdate
+ (this->naming_context_.fetch ("lastUpdate"));
+
+ if (!lastUpdate.get ())
+ {
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("No data to graph\n")));
+ return;
+ }
+ // Listing 2
+
+ // Listing 3 code/ch21
+ Name_Binding_Ptr lastGraphed
+ (this->naming_context_.fetch ("lastGraphed"));
+
+ if (lastGraphed.get () &&
+ lastGraphed->int_value () == lastUpdate->int_value ())
+ {
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Data already graphed\n")));
+ return;
+ }
+ // Listing 3
+
+ // Listing 4 code/ch21
+ ACE_BINDING_SET set;
+ if (this->naming_context_.list_name_entries
+ (set, "history[") != 0)
+ {
+ ACE_DEBUG ((LM_INFO,
+ ACE_TEXT ("There's nothing to graph\n")));
+ return;
+ }
+ // Listing 4
+
+ // Listing 5 code/ch21
+ Graphable_Element_List graphable;
+ ACE_BINDING_ITERATOR set_iterator (set);
+ for (ACE_Name_Binding *entry = 0;
+ set_iterator.next (entry) != 0;
+ set_iterator.advance ())
+ {
+ Name_Binding binding (entry);
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("%s\t%s\t%s\n"),
+ binding.type (),
+ binding.name (),
+ binding.value ()));
+
+ Graphable_Element *ge = new Graphable_Element (entry);
+ graphable.push_back (*ge);
+ }
+ // Listing 5
+
+ // Listing 6 code/ch21
+ Graph g;
+ g.graph (lastUpdate->value (), graphable);
+ this->naming_context_.rebind ("lastGraphed",
+ lastUpdate->int_value ());
+ // Listing 6
+}
diff --git a/ACE/examples/APG/Naming/Temperature_Grapher.h b/ACE/examples/APG/Naming/Temperature_Grapher.h
new file mode 100644
index 00000000000..610dac6a578
--- /dev/null
+++ b/ACE/examples/APG/Naming/Temperature_Grapher.h
@@ -0,0 +1,30 @@
+// $Id$
+
+#ifndef TEMPERATURE_GRAPHER_H
+#define TEMPERATURE_GRAPHER_H
+
+#include "Thermometer.h"
+#include "Temperature_Grapher_Options.h"
+#include "Naming_Context.h"
+
+class Temperature_Grapher
+ {
+ public:
+ Temperature_Grapher( Temperature_Grapher_Options & opt,
+ Naming_Context & naming_context )
+ : opt_(opt), naming_context_(naming_context)
+ {
+ }
+
+ void monitor();
+
+ protected:
+ void update_graph();
+
+ private:
+ Thermometer * thermometer_;
+ Temperature_Grapher_Options & opt_;
+ Naming_Context & naming_context_;
+ };
+
+#endif /* TEMPERATURE_GRAPHER_H */
diff --git a/ACE/examples/APG/Naming/Temperature_Grapher_Options.h b/ACE/examples/APG/Naming/Temperature_Grapher_Options.h
new file mode 100644
index 00000000000..e7a2dbe7c94
--- /dev/null
+++ b/ACE/examples/APG/Naming/Temperature_Grapher_Options.h
@@ -0,0 +1,21 @@
+// $Id$
+
+#ifndef TEMPERATURE_GRAPHER_OPTIONS_H
+#define TEMPERATURE_GRAPHER_OPTIONS_H
+
+class Temperature_Grapher_Options
+ {
+ public:
+ Temperature_Grapher_Options( int argc, ACE_TCHAR ** argv )
+ {
+ ACE_UNUSED_ARG(argc);
+ ACE_UNUSED_ARG(argv);
+ }
+
+ int poll_interval()
+ {
+ return 20; // every 20 seconds
+ }
+ };
+
+#endif /* TEMPERATURE_GRAPHER_OPTIONS_H */
diff --git a/ACE/examples/APG/Naming/Temperature_Monitor.cpp b/ACE/examples/APG/Naming/Temperature_Monitor.cpp
new file mode 100644
index 00000000000..8ac841b4108
--- /dev/null
+++ b/ACE/examples/APG/Naming/Temperature_Monitor.cpp
@@ -0,0 +1,133 @@
+// $Id$
+
+#include "ace/OS_NS_time.h"
+#include "ace/OS_NS_unistd.h"
+#include "ace/Log_Msg.h"
+
+#include "Thermometer.h"
+#include "Temperature_Monitor.h"
+#include "EMail.h"
+
+// Listing 1 code/ch21
+Temperature_Monitor::Temperature_Monitor
+ (Temperature_Monitor_Options &opt,
+ Naming_Context &naming_context)
+ : opt_(opt), naming_context_(naming_context)
+{ }
+// Listing 1
+
+// Listing 31 code/ch21
+void Temperature_Monitor::record_temperature (float temp)
+{
+ Name_Binding_Ptr current
+ (this->naming_context_.fetch ("current"));
+ if (current.get())
+ {
+ this->naming_context_.rebind ("previous",
+ current->value ());
+ }
+// Listing 31
+
+// Listing 32 code/ch21
+ this->naming_context_.rebind ("current", temp);
+// Listing 32
+
+// Listing 33 code/ch21
+ this->naming_context_.unbind ("lastReset");
+ this->naming_context_.unbind ("resetCount");
+// Listing 33
+}
+
+// Listing 41 code/ch21
+void Temperature_Monitor::record_failure (void)
+{
+ Name_Binding_Ptr lastReset
+ (this->naming_context_.fetch ("lastReset"));
+ Name_Binding_Ptr resetCount
+ (this->naming_context_.fetch ("resetCount"));
+// Listing 41
+
+// Listing 42 code/ch21
+ int now = ACE_OS::time ();
+ int lastResetTime;
+ if (lastReset.get ())
+ {
+ lastResetTime = lastReset->int_value ();
+ }
+ else
+ {
+ this->naming_context_.rebind ("lastReset", now);
+ lastResetTime = now;
+ }
+ // Listing 42
+
+ // Listing 43 code/ch21
+ if (now - lastResetTime > this->opt_.reset_interval ())
+ {
+ this->reset_device (resetCount);
+ }
+ // Listing 43
+}
+
+// Listing 5 code/ch21
+void
+Temperature_Monitor::reset_device (Name_Binding_Ptr &resetCount)
+{
+ int number_of_resets = 1;
+ if (resetCount.get ())
+ {
+ number_of_resets = resetCount->int_value () + 1;
+ if (number_of_resets > this->opt_.excessive_resets ())
+ {
+ // Exclude 5
+ EMail notification;
+
+ char message[BUFSIZ];
+ ACE_OS::sprintf (message,
+ "Thermometer: %s\n"
+ "Reset Count: %d\n",
+ this->thermometer_->address(),
+ number_of_resets);
+
+ notification.send (this->opt_.admin_email (),
+ this->opt_.email_from (),
+ "Excessive number of thermometer resets",
+ message);
+ // Exclude 5
+ }
+ }
+ this->thermometer_->reset ();
+ this->naming_context_.rebind ("lastReset",
+ (int) ACE_OS::time ());
+ this->naming_context_.rebind ("resetCount",
+ number_of_resets);
+}
+// Listing 5
+
+// Listing 2 code/ch21
+void Temperature_Monitor::monitor (void)
+{
+ this->thermometer_ =
+ new Thermometer (this->opt_.thermometer_address ());
+
+ for(;;)
+ {
+ float temp = this->thermometer_->temperature ();
+ ACE_DEBUG ((LM_INFO, ACE_TEXT ("Read temperature %.2f\n"),
+ temp));
+
+ if (temp >= 0)
+ {
+ this->record_temperature (temp);
+ }
+ else
+ {
+ this->record_failure ();
+ }
+
+ ACE_OS::sleep (this->opt_.poll_interval ());
+ }
+
+ delete this->thermometer_;
+}
+// Listing 2
diff --git a/ACE/examples/APG/Naming/Temperature_Monitor.h b/ACE/examples/APG/Naming/Temperature_Monitor.h
new file mode 100644
index 00000000000..3b85b100fa1
--- /dev/null
+++ b/ACE/examples/APG/Naming/Temperature_Monitor.h
@@ -0,0 +1,29 @@
+// $Id$
+
+#ifndef TEMPERATURE_MONITOR_H
+#define TEMPERATURE_MONITOR_H
+
+#include "Thermometer.h"
+#include "Temperature_Monitor_Options.h"
+#include "Naming_Context.h"
+
+class Temperature_Monitor
+ {
+ public:
+ Temperature_Monitor( Temperature_Monitor_Options & opt,
+ Naming_Context & naming_context );
+
+ void monitor();
+
+ protected:
+ void record_temperature(float temp);
+ void record_failure();
+ void reset_device(Name_Binding_Ptr & resetCount);
+
+ private:
+ Thermometer * thermometer_;
+ Temperature_Monitor_Options & opt_;
+ Naming_Context & naming_context_;
+ };
+
+#endif /* TEMPERATURE_MONITOR_H */
diff --git a/ACE/examples/APG/Naming/Temperature_Monitor2.cpp b/ACE/examples/APG/Naming/Temperature_Monitor2.cpp
new file mode 100644
index 00000000000..b24f1c1f329
--- /dev/null
+++ b/ACE/examples/APG/Naming/Temperature_Monitor2.cpp
@@ -0,0 +1,145 @@
+// $Id$
+
+#include "ace/OS_NS_time.h"
+#include "ace/OS_NS_unistd.h"
+#include "ace/Log_Msg.h"
+
+#include "Thermometer.h"
+#include "Temperature_Monitor2.h"
+#include "EMail.h"
+
+// Listing 1 code/ch21
+void Temperature_Monitor2::record_temperature (float temp)
+{
+ Name_Binding_Ptr current
+ (this->naming_context_.fetch ("current"));
+ if (current.get ())
+ {
+ this->naming_context_.rebind ("previous",
+ current->value ());
+ }
+
+ this->record_history (temp);
+
+ this->naming_context_.unbind ("lastFailure");
+ this->naming_context_.unbind ("lastReset");
+ this->naming_context_.unbind ("resetCount");
+}
+// Listing 1
+
+// Listing 2 code/ch21
+void Temperature_Monitor2::record_history (float temp)
+{
+ int now = (int)ACE_OS::time ();
+ this->shared_context_.rebind ("lastUpdate", now);
+
+ Name_Binding_Ptr counter
+ (this->shared_context_.fetch ("counter"));
+ int counterValue = counter.get () ? counter->int_value () : 0;
+
+ char name[BUFSIZ];
+ ACE_OS::sprintf (name, "history[%d]", counterValue);
+
+ char value[BUFSIZ];
+ ACE_OS::sprintf (value, "%d|%.2f", now, temp);
+
+ this->shared_context_.rebind (name, value);
+
+ ++counterValue;
+ counterValue %= this->opt_.history_size ();
+ this->shared_context_.rebind ("counter", counterValue);
+}
+// Listing 2
+
+void Temperature_Monitor2::reset_device (Name_Binding_Ptr &resetCount)
+{
+ int number_of_resets = 1;
+
+ if (resetCount.get ())
+ {
+ number_of_resets = resetCount->int_value () + 1;
+
+ if (number_of_resets > this->opt_.excessive_resets ())
+ {
+ EMail notification;
+
+ char message[BUFSIZ];
+ ACE_OS::sprintf (message,
+ "Thermometer: %s\n"
+ "Reset Count: %d\n",
+ this->thermometer_->address (),
+ number_of_resets);
+
+ notification.send (this->opt_.admin_email (),
+ this->opt_.email_from (),
+ "Excessive number of thermometer resets",
+ message);
+ }
+ }
+
+ this->thermometer_->reset ();
+
+ this->naming_context_.rebind ("lastReset", (int)ACE_OS::time ());
+ this->naming_context_.rebind ("resetCount", number_of_resets);
+}
+
+void Temperature_Monitor2::record_failure (void)
+{
+ Name_Binding_Ptr lastFailure (this->naming_context_.fetch ("lastFailure"));
+ Name_Binding_Ptr lastReset (this->naming_context_.fetch ("lastReset"));
+ Name_Binding_Ptr resetCount (this->naming_context_.fetch ("resetCount"));
+
+ int now = ACE_OS::time ();
+
+ int lastFailureTime;
+ int lastResetTime = 0;
+
+ if (lastFailure.get ())
+ {
+ lastFailureTime = lastFailure->int_value ();
+ }
+ else
+ {
+ this->naming_context_.rebind ("firstFailure", now);
+ this->naming_context_.rebind ("lastReset", now);
+ lastFailureTime = now;
+ lastResetTime = now;
+ }
+
+ if (lastReset.get ())
+ {
+ lastResetTime = lastReset->int_value ();
+ }
+
+ if (now - lastResetTime > this->opt_.reset_interval ())
+ {
+ this->reset_device (resetCount);
+ }
+
+ this->naming_context_.rebind ("lastFailure", now);
+}
+
+void Temperature_Monitor2::monitor (void)
+{
+ this->thermometer_ = new Thermometer (this->opt_.thermometer_address ());
+
+ for (;;)
+ {
+ float temp = this->thermometer_->temperature ();
+
+ ACE_DEBUG ((LM_INFO, ACE_TEXT ("Read temperature %.2f\n"), temp));
+
+ if (temp >= 0)
+ {
+ this->record_temperature (temp);
+ }
+ else
+ {
+ this->record_failure ();
+ }
+
+ ACE_OS::sleep (this->opt_.poll_interval ());
+ }
+
+ delete this->thermometer_;
+}
diff --git a/ACE/examples/APG/Naming/Temperature_Monitor2.h b/ACE/examples/APG/Naming/Temperature_Monitor2.h
new file mode 100644
index 00000000000..b887e5c8e4c
--- /dev/null
+++ b/ACE/examples/APG/Naming/Temperature_Monitor2.h
@@ -0,0 +1,36 @@
+// $Id$
+
+#ifndef TEMPERATURE_MONITOR_H
+#define TEMPERATURE_MONITOR_H
+
+#include "Thermometer.h"
+#include "Temperature_Monitor_Options.h"
+#include "Naming_Context.h"
+
+class Temperature_Monitor2
+{
+public:
+ Temperature_Monitor2 (Temperature_Monitor_Options & opt,
+ Naming_Context & naming_context,
+ Naming_Context & shared_context)
+ : opt_(opt),
+ naming_context_(naming_context),
+ shared_context_(shared_context)
+ { }
+
+ void monitor (void);
+
+protected:
+ void record_temperature (float temp);
+ void record_history (float temp);
+ void record_failure (void);
+ void reset_device (Name_Binding_Ptr & resetCount);
+
+private:
+ Thermometer *thermometer_;
+ Temperature_Monitor_Options &opt_;
+ Naming_Context &naming_context_;
+ Naming_Context &shared_context_;
+};
+
+#endif /* TEMPERATURE_MONITOR_H */
diff --git a/ACE/examples/APG/Naming/Temperature_Monitor_Options.h b/ACE/examples/APG/Naming/Temperature_Monitor_Options.h
new file mode 100644
index 00000000000..95fb82faa9b
--- /dev/null
+++ b/ACE/examples/APG/Naming/Temperature_Monitor_Options.h
@@ -0,0 +1,48 @@
+// $Id$
+
+#ifndef TEMPERATURE_MONITOR_OPTIONS_H
+#define TEMPERATURE_MONITOR_OPTIONS_H
+
+class Temperature_Monitor_Options
+ {
+ public:
+ Temperature_Monitor_Options (int, ACE_TCHAR *[])
+ { }
+
+ const char *thermometer_address (void)
+ {
+ return "serial:// s0/0x3e52";
+ }
+
+ int poll_interval (void)
+ {
+ return 10; // every 10 seconds
+ }
+
+ int reset_interval (void)
+ {
+ return 60; // sixty seconds
+ }
+
+ int excessive_resets (void)
+ {
+ return 5; // no response in 5 minutes
+ }
+
+ const char *admin_email (void)
+ {
+ return "root@localhost";
+ }
+
+ const char *email_from (void)
+ {
+ return "temperature monitor";
+ }
+
+ int history_size()
+ {
+ return 10;
+ }
+ };
+
+#endif /* TEMPERATURE_MONITOR_OPTIONS_H */
diff --git a/ACE/examples/APG/Naming/Thermometer.h b/ACE/examples/APG/Naming/Thermometer.h
new file mode 100644
index 00000000000..cfdf1ca0f3d
--- /dev/null
+++ b/ACE/examples/APG/Naming/Thermometer.h
@@ -0,0 +1,48 @@
+/* -*- C++ -*- */
+// $Id$
+
+#ifndef THERMOMETER_H
+#define THERMOMETER_H
+
+#include "ace/OS_NS_stdlib.h"
+#include "ace/Log_Msg.h"
+
+class Thermometer
+{
+public:
+ Thermometer (const char *addr)
+ : addr_(addr), threshold_(5)
+ { }
+
+ float temperature (void)
+ {
+ int success = ACE_OS::rand () % 10;
+ if (success < this->threshold_)
+ {
+ this->threshold_ = 7;
+ return -1.0;
+ }
+
+ this->threshold_ = 3;
+ int itemp = 80 + ACE_OS::rand () % 10; // 80 <= t <= 90
+ return (float)itemp;
+ }
+
+ const char *address (void)
+ {
+ return this->addr_;
+ }
+
+ void reset (void)
+ {
+ this->threshold_ = 4;
+ ACE_DEBUG ((LM_ERROR, ACE_TEXT ("Resetting thermometer %C\n"),
+ this->address ()));
+ }
+
+private:
+ const char *addr_;
+ int threshold_;
+};
+
+#endif /* THERMOMETER_H */
diff --git a/ACE/examples/APG/Naming/naming.mpc b/ACE/examples/APG/Naming/naming.mpc
new file mode 100644
index 00000000000..fda823954fc
--- /dev/null
+++ b/ACE/examples/APG/Naming/naming.mpc
@@ -0,0 +1,50 @@
+// -*- MPC -*-
+// $Id$
+
+project(Netlocal) : aceexe {
+ avoids += ace_for_tao
+ exename = Netlocal
+ Source_Files {
+ Netlocal.cpp
+ Temperature_Monitor2.cpp
+ }
+}
+
+project(Netlocal Reader) : aceexe {
+ avoids += ace_for_tao
+ exename = Netlocal_reader
+ Source_Files {
+ Netlocal_reader.cpp
+ Graph.cpp
+ Temperature_Grapher.cpp
+ }
+}
+
+project(Nodelocal) : aceexe {
+ avoids += ace_for_tao
+ exename = Nodelocal
+ Source_Files {
+ Nodelocal.cpp
+ Temperature_Monitor.cpp
+ }
+}
+
+project(Nodelocal Shared) : aceexe {
+ avoids += ace_for_tao
+ exename = Nodelocal_shared
+ Source_Files {
+ Nodelocal_shared.cpp
+ Temperature_Monitor2.cpp
+ }
+}
+
+project(Nodelocal Shared Reader) : aceexe {
+ avoids += ace_for_tao
+ exename = Nodelocal_shared_reader
+ Source_Files {
+ Nodelocal_shared_reader.cpp
+ Graph.cpp
+ Temperature_Grapher.cpp
+ Temperature_Monitor.cpp
+ }
+}
diff --git a/ACE/examples/APG/Naming/svc.conf b/ACE/examples/APG/Naming/svc.conf
new file mode 100644
index 00000000000..550ef992177
--- /dev/null
+++ b/ACE/examples/APG/Naming/svc.conf
@@ -0,0 +1 @@
+dynamic Name_Server Service_Object * netsvcs:_make_ACE_Name_Acceptor() "-p 20012"
diff --git a/ACE/examples/APG/Proactor/.cvsignore b/ACE/examples/APG/Proactor/.cvsignore
new file mode 100644
index 00000000000..64b35fb3d57
--- /dev/null
+++ b/ACE/examples/APG/Proactor/.cvsignore
@@ -0,0 +1,2 @@
+HA_Proactive_Status
+HA_Proactive_Status
diff --git a/ACE/examples/APG/Proactor/HA_Proactive_Status.cpp b/ACE/examples/APG/Proactor/HA_Proactive_Status.cpp
new file mode 100644
index 00000000000..9d9b9dfb0e5
--- /dev/null
+++ b/ACE/examples/APG/Proactor/HA_Proactive_Status.cpp
@@ -0,0 +1,163 @@
+/*
+** $Id$
+**
+** Example program from The ACE Programmer's Guide, Chapter 8.
+** Copyright 2003 Addison-Wesley. All Rights Reserved.
+*/
+
+#include "HA_Proactive_Status.h"
+#include "ace/Log_Msg.h"
+#include "ace/Message_Block.h"
+#include "ace/Proactor.h"
+#include "ace/os_include/arpa/os_inet.h"
+
+#if (defined (ACE_WIN32) && !defined (ACE_HAS_WINCE)) || (defined (ACE_HAS_AIO_CALLS))
+
+// Listing 1 code/ch08
+void
+HA_Proactive_Service::open (ACE_HANDLE h, ACE_Message_Block&)
+{
+ this->handle (h);
+ if (this->reader_.open (*this) != 0 ||
+ this->writer_.open (*this) != 0 )
+ {
+ ACE_ERROR ((LM_ERROR, ACE_TEXT ("%p\n"),
+ ACE_TEXT ("HA_Proactive_Service open")));
+ delete this;
+ return;
+ }
+
+ ACE_Message_Block *mb;
+ ACE_NEW_NORETURN (mb, ACE_Message_Block (1024));
+ if (this->reader_.read (*mb, mb->space ()) != 0)
+ {
+ ACE_ERROR ((LM_ERROR, ACE_TEXT ("%p\n"),
+ ACE_TEXT ("HA_Proactive_Service begin read")));
+ mb->release ();
+ delete this;
+ return;
+ }
+
+ // mb is now controlled by Proactor framework.
+ return;
+}
+// Listing 1
+
+// Listing 2 code/ch08
+void
+HA_Proactive_Service::handle_read_stream
+ (const ACE_Asynch_Read_Stream::Result &result)
+{
+ ACE_Message_Block &mb = result.message_block ();
+ if (!result.success () || result.bytes_transferred () == 0)
+ {
+ mb.release ();
+ delete this;
+ }
+ else
+ {
+ if (this->writer_.write (mb, mb.length ()) != 0)
+ {
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("starting write")));
+ mb.release ();
+ }
+ else
+ {
+ ACE_Message_Block *new_mb;
+ ACE_NEW_NORETURN (new_mb, ACE_Message_Block (1024));
+ this->reader_.read (*new_mb, new_mb->space ());
+ }
+ }
+ return;
+}
+// Listing 2
+
+// Listing 3 code/ch08
+void
+HA_Proactive_Service::handle_write_stream
+(const ACE_Asynch_Write_Stream::Result &result)
+{
+ result.message_block ().release ();
+ return;
+}
+// Listing 3
+
+// The network address check only works for BSD-ish systems. This
+// sort of network number accessor should be added to ACE_INET_Addr
+// at some point...
+#if defined (ACE_WIN32)
+int
+HA_Proactive_Acceptor::validate_connection
+(const ACE_Asynch_Accept::Result&,
+ const ACE_INET_Addr&,
+ const ACE_INET_Addr&)
+{
+ return 0;
+}
+#else
+
+// Listing 4 code/ch08
+int
+HA_Proactive_Acceptor::validate_connection (
+ const ACE_Asynch_Accept::Result&,
+ const ACE_INET_Addr& remote,
+ const ACE_INET_Addr& local)
+{
+ struct in_addr *remote_addr =
+ reinterpret_cast<struct in_addr*> (remote.get_addr ());
+ struct in_addr *local_addr =
+ reinterpret_cast<struct in_addr*> (local.get_addr ());
+ if (inet_netof (*local_addr) == inet_netof (*remote_addr))
+ return 0;
+
+ return -1;
+}
+// Listing 4
+
+#endif /* ACE_WIN32 */
+
+int
+ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ // Listing 5 code/ch08
+ ACE_INET_Addr listen_addr; // Set up with listen port
+ HA_Proactive_Acceptor aio_acceptor;
+ if (0 != aio_acceptor.open (listen_addr,
+ 0, // bytes_to_read
+ 0, // pass_addresses
+ ACE_DEFAULT_BACKLOG,
+ 1, // reuse_addr
+ 0, // proactor
+ 1)) // validate_new_connection
+ ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("%p\n"),
+ ACE_TEXT ("acceptor open")), 1);
+ // Listing 5
+
+#if 0
+ // Listing 6 code/ch08
+ ACE_INET_Addr peer_addr; // Set up peer addr
+ ACE_Asynch_Connector<HA_Proactive_Service> aio_connect;
+ aio_connect.connect (peer_addr);
+ // Listing 6
+#endif
+
+ // Listing 7 code/ch08
+ ACE_Proactor::instance ()->proactor_run_event_loop ();
+ // Listing 7
+ return 0;
+}
+
+#else
+
+int
+ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("This example requires asynchronous I/O support.\n")));
+ return 1;
+}
+
+#endif /* (ACE_WIN32 && != ACE_HAS_WINCE) || ACE_HAS_AIO_CALLS*/
+
diff --git a/ACE/examples/APG/Proactor/HA_Proactive_Status.h b/ACE/examples/APG/Proactor/HA_Proactive_Status.h
new file mode 100644
index 00000000000..f66080b62cd
--- /dev/null
+++ b/ACE/examples/APG/Proactor/HA_Proactive_Status.h
@@ -0,0 +1,87 @@
+/* -*- C++ -*- */
+/*
+** $Id$
+**
+** Example program from The ACE Programmer's Guide, Chapter 8.
+** Copyright 2003 Addison-Wesley. All Rights Reserved.
+*/
+
+#ifndef __HA_PROACTIVE_STATUS_H
+#define __HA_PROACTIVE_STATUS_H
+
+#include "ace/OS_NS_sys_socket.h"
+#include "ace/Asynch_IO.h"
+#include "ace/Service_Object.h"
+// Listing 1 code/ch08
+#include "ace/Asynch_IO.h"
+
+#if (defined (ACE_WIN32) && !defined (ACE_HAS_WINCE)) || (defined (ACE_HAS_AIO_CALLS))
+
+class HA_Proactive_Service : public ACE_Service_Handler
+{
+public:
+ ~HA_Proactive_Service ()
+ {
+ if (this->handle () != ACE_INVALID_HANDLE)
+ ACE_OS::closesocket (this->handle ());
+ }
+
+ virtual void open (ACE_HANDLE h, ACE_Message_Block&);
+
+ // This method will be called when an asynchronous read
+ // completes on a stream.
+ virtual void handle_read_stream
+ (const ACE_Asynch_Read_Stream::Result &result);
+
+ // This method will be called when an asynchronous write
+ // completes on a stream.
+ virtual void handle_write_stream
+ (const ACE_Asynch_Write_Stream::Result &result);
+
+private:
+ ACE_Asynch_Read_Stream reader_;
+ ACE_Asynch_Write_Stream writer_;
+};
+// Listing 1
+
+// Listing 2 code/ch08
+#include "ace/Asynch_Acceptor.h"
+#include "ace/INET_Addr.h"
+
+class HA_Proactive_Acceptor :
+ public ACE_Asynch_Acceptor<HA_Proactive_Service>
+{
+public:
+ virtual int validate_connection
+ (const ACE_Asynch_Accept::Result& result,
+ const ACE_INET_Addr &remote,
+ const ACE_INET_Addr &local);
+};
+// Listing 2
+
+#endif /* (ACE_WIN32 && != ACE_HAS_WINCE) || ACE_HAS_AIO_CALLS*/
+
+#if 0
+// Listing 3 code/ch08
+template <class HANDLER>
+class ACE_Asynch_Acceptor : public ACE_Handler
+ ...
+protected:
+ virtual HANDLER *make_handler (void)
+ {
+ return new HANDLER;
+ }
+// Listing 3
+#endif
+
+class HA_Proactive_Status : public ACE_Service_Object
+{
+public:
+ // Initializes object when dynamic linking occurs.
+ virtual int init (int argc, ACE_TCHAR *argv[]);
+
+ // Terminates object when dynamic unlinking occurs.
+ virtual int fini (void);
+};
+
+#endif /* __HA_PROACTIVE_STATUS_H */
diff --git a/ACE/examples/APG/Proactor/Makefile.am b/ACE/examples/APG/Proactor/Makefile.am
new file mode 100644
index 00000000000..a7632af1d4f
--- /dev/null
+++ b/ACE/examples/APG/Proactor/Makefile.am
@@ -0,0 +1,39 @@
+## Process this file with automake to create Makefile.in
+##
+## $Id$
+##
+## This file was generated by MPC. Any changes made directly to
+## this file will be lost the next time it is generated.
+##
+## MPC Command:
+## /acebuilds/ACE_wrappers-repository/bin/mwc.pl -include /acebuilds/MPC/config -include /acebuilds/MPC/templates -feature_file /acebuilds/ACE_wrappers-repository/local.features -noreldefs -type automake -exclude build,Kokyu
+
+ACE_BUILDDIR = $(top_builddir)
+ACE_ROOT = $(top_srcdir)
+
+
+## Makefile.HA_Proactive_Status.am
+
+if !BUILD_ACE_FOR_TAO
+noinst_PROGRAMS = HA_Proactive_Status
+
+HA_Proactive_Status_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+HA_Proactive_Status_SOURCES = \
+ HA_Proactive_Status.cpp \
+ HA_Proactive_Status.h
+
+HA_Proactive_Status_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+endif !BUILD_ACE_FOR_TAO
+
+## Clean up template repositories, etc.
+clean-local:
+ -rm -f *~ *.bak *.rpo *.sym lib*.*_pure_* core core.*
+ -rm -f gcctemp.c gcctemp so_locations *.ics
+ -rm -rf cxx_repository ptrepository ti_files
+ -rm -rf templateregistry ir.out
+ -rm -rf ptrepository SunWS_cache Templates.DB
diff --git a/ACE/examples/APG/Proactor/proactor.mpc b/ACE/examples/APG/Proactor/proactor.mpc
new file mode 100644
index 00000000000..85ef950ae66
--- /dev/null
+++ b/ACE/examples/APG/Proactor/proactor.mpc
@@ -0,0 +1,10 @@
+// -*- MPC -*-
+// $Id$
+
+project(HA Proactive Status) : aceexe {
+ avoids += ace_for_tao
+ exename = HA_Proactive_Status
+ Source_Files {
+ HA_Proactive_Status.cpp
+ }
+}
diff --git a/ACE/examples/APG/Processes/.cvsignore b/ACE/examples/APG/Processes/.cvsignore
new file mode 100644
index 00000000000..187cf413af2
--- /dev/null
+++ b/ACE/examples/APG/Processes/.cvsignore
@@ -0,0 +1,8 @@
+Process_Manager_Death
+Process_Manager_Death
+Process_Manager_Spawn
+Process_Manager_Spawn
+Process_Mutex
+Process_Mutex
+Spawn
+Spawn
diff --git a/ACE/examples/APG/Processes/Makefile.am b/ACE/examples/APG/Processes/Makefile.am
new file mode 100644
index 00000000000..5c45a506304
--- /dev/null
+++ b/ACE/examples/APG/Processes/Makefile.am
@@ -0,0 +1,90 @@
+## Process this file with automake to create Makefile.in
+##
+## $Id$
+##
+## This file was generated by MPC. Any changes made directly to
+## this file will be lost the next time it is generated.
+##
+## MPC Command:
+## /acebuilds/ACE_wrappers-repository/bin/mwc.pl -include /acebuilds/MPC/config -include /acebuilds/MPC/templates -feature_file /acebuilds/ACE_wrappers-repository/local.features -noreldefs -type automake -exclude build,Kokyu
+
+ACE_BUILDDIR = $(top_builddir)
+ACE_ROOT = $(top_srcdir)
+
+noinst_PROGRAMS =
+
+## Makefile.Process_Manager_Death.am
+
+if !BUILD_ACE_FOR_TAO
+noinst_PROGRAMS += Process_Manager_Death
+
+Process_Manager_Death_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+Process_Manager_Death_SOURCES = \
+ Process_Manager_Death.cpp
+
+Process_Manager_Death_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+endif !BUILD_ACE_FOR_TAO
+
+## Makefile.Process_Manager_Spawn.am
+
+if !BUILD_ACE_FOR_TAO
+noinst_PROGRAMS += Process_Manager_Spawn
+
+Process_Manager_Spawn_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+Process_Manager_Spawn_SOURCES = \
+ Process_Manager_Spawn.cpp
+
+Process_Manager_Spawn_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+endif !BUILD_ACE_FOR_TAO
+
+## Makefile.Process_Mutex.am
+
+if !BUILD_ACE_FOR_TAO
+noinst_PROGRAMS += Process_Mutex
+
+Process_Mutex_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+Process_Mutex_SOURCES = \
+ Process_Mutex.cpp
+
+Process_Mutex_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+endif !BUILD_ACE_FOR_TAO
+
+## Makefile.Spawn.am
+
+if !BUILD_ACE_FOR_TAO
+noinst_PROGRAMS += Spawn
+
+Spawn_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+Spawn_SOURCES = \
+ Spawn.cpp
+
+Spawn_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+endif !BUILD_ACE_FOR_TAO
+
+## Clean up template repositories, etc.
+clean-local:
+ -rm -f *~ *.bak *.rpo *.sym lib*.*_pure_* core core.*
+ -rm -f gcctemp.c gcctemp so_locations *.ics
+ -rm -rf cxx_repository ptrepository ti_files
+ -rm -rf templateregistry ir.out
+ -rm -rf ptrepository SunWS_cache Templates.DB
diff --git a/ACE/examples/APG/Processes/Process_Manager_Death.cpp b/ACE/examples/APG/Processes/Process_Manager_Death.cpp
new file mode 100644
index 00000000000..51a8d911458
--- /dev/null
+++ b/ACE/examples/APG/Processes/Process_Manager_Death.cpp
@@ -0,0 +1,67 @@
+// $Id$
+
+#include "ace/Log_Msg.h"
+#include "ace/Process_Manager.h"
+#include "ace/Reactor.h"
+
+static const int NCHILDREN = 2;
+
+// Listing 1 code/ch10
+class DeathHandler: public ACE_Event_Handler
+{
+public:
+ DeathHandler () : count_(0)
+ {
+ ACE_TRACE (ACE_TEXT ("DeathHandler::DeathHandler"));
+ }
+
+ virtual int handle_exit (ACE_Process * process)
+ {
+ ACE_TRACE (ACE_TEXT ("DeathHandler::handle_exit"));
+
+ ACE_DEBUG
+ ((LM_DEBUG,
+ ACE_TEXT ("Process %d exited with exit code %d\n"),
+ process->getpid (), process->return_value ()));
+
+ if (++count_ == NCHILDREN)
+ ACE_Reactor::instance ()->end_reactor_event_loop ();
+
+ return 0;
+ }
+
+private:
+ int count_;
+};
+// Listing 1
+// Listing 0 code/ch10
+int ACE_TMAIN (int argc, ACE_TCHAR *argv[])
+{
+ if (argc > 1) // Running as a child.
+ return 0;
+
+ // Instantiate a process manager with space for
+ // 10 processes.
+ ACE_Process_Manager pm (10, ACE_Reactor::instance ());
+
+ // Create a process termination handler.
+ DeathHandler handler;
+
+ // Specify the options for the new processes to be spawned.
+ ACE_Process_Options options;
+ options.command_line (ACE_TEXT ("%s a"), argv[0]);
+
+ // Spawn two child processes.
+ pid_t pids[NCHILDREN];
+ pm.spawn_n (NCHILDREN, options, pids);
+
+ // Register handler to be called when these processes exit.
+ for (int i = 0; i < NCHILDREN; i++)
+ pm.register_handler (&handler, pids[i]);
+
+ // Run the reactor event loop waiting for events to occur.
+ ACE_Reactor::instance ()->run_reactor_event_loop ();
+
+ return 0;
+}
+// Listing 0
diff --git a/ACE/examples/APG/Processes/Process_Manager_Spawn.cpp b/ACE/examples/APG/Processes/Process_Manager_Spawn.cpp
new file mode 100644
index 00000000000..dd61ae9bae8
--- /dev/null
+++ b/ACE/examples/APG/Processes/Process_Manager_Spawn.cpp
@@ -0,0 +1,59 @@
+// $Id$
+
+#include "ace/OS_NS_unistd.h"
+#include "ace/Log_Msg.h"
+// Listing 0 code/ch10
+#include "ace/Process_Manager.h"
+
+static const int NCHILDREN = 2;
+
+int ACE_TMAIN (int argc, ACE_TCHAR *argv[])
+{
+ if (argc > 1) // Running as a child.
+ {
+ ACE_OS::sleep (10);
+ }
+ else // Running as a parent.
+ {
+ // Get the processwide process manager.
+ ACE_Process_Manager* pm = ACE_Process_Manager::instance ();
+
+ // Specify the options for the new processes
+ // to be spawned.
+ ACE_Process_Options options;
+ options.command_line (ACE_TEXT ("%s a"), argv[0]);
+
+ // Spawn two child processes.
+ pid_t pids[NCHILDREN];
+ pm->spawn_n (NCHILDREN, options, pids);
+
+ // Destroy the first child.
+ pm->terminate (pids[0]);
+
+ // Wait for the child we just terminated.
+ ACE_exitcode status;
+ pm->wait (pids[0], &status);
+
+ // Get the results of the termination.
+
+#if !defined(ACE_WIN32)
+ if (WIFSIGNALED (status) != 0)
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("%d died because of a signal ")
+ ACE_TEXT ("of type %d\n"),
+ pids[0], WTERMSIG (status)));
+#else
+ ACE_DEBUG
+ ((LM_DEBUG,
+ ACE_TEXT ("The process terminated with exit code %d\n"),
+ status));
+#endif /*ACE_WIN32*/
+
+ // Wait for all (only one left) of the
+ // children to exit.
+ pm->wait (0);
+ }
+
+ return 0;
+}
+// Listing 0
diff --git a/ACE/examples/APG/Processes/Process_Mutex.cpp b/ACE/examples/APG/Processes/Process_Mutex.cpp
new file mode 100644
index 00000000000..2afb89803b9
--- /dev/null
+++ b/ACE/examples/APG/Processes/Process_Mutex.cpp
@@ -0,0 +1,79 @@
+// $Id$
+
+#include "ace/OS_NS_unistd.h"
+#include "ace/Log_Msg.h"
+#include "ace/Process.h"
+#include "ace/Process_Mutex.h"
+
+// Listing 1 code/ch10
+class GResourceUser
+{
+public:
+ GResourceUser (ACE_Process_Mutex &mutex) : gmutex_(mutex)
+ {
+ ACE_TRACE (ACE_TEXT ("GResourceUser::GResourceUser"));
+ }
+
+ void run (void)
+ {
+ ACE_TRACE (ACE_TEXT ("GResourceUser::run"));
+
+ int count = 0;
+ while (count++ < 10)
+ {
+ int result = this->gmutex_.acquire ();
+ ACE_ASSERT (result == 0);
+
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("(%P| %t) has the mutex\n")));
+
+ // Access Global resource
+ ACE_OS::sleep (1);
+
+ result = this->gmutex_.release ();
+ ACE_ASSERT (result == 0);
+ ACE_OS::sleep (1); // Give other process a chance.
+ }
+ }
+
+private:
+ ACE_Process_Mutex &gmutex_;
+};
+// Listing 1
+
+// Listing 0 code/ch10
+int ACE_TMAIN (int argc, ACE_TCHAR *argv[])
+{
+ if (argc > 1) // Run as the child.
+ {
+ // Create or get the global mutex.
+ ACE_Process_Mutex mutex ("GlobalMutex");
+
+ GResourceUser acquirer (mutex);
+ acquirer.run ();
+ }
+ else // Run as the parent.
+ {
+ ACE_Process_Options options;
+ options.command_line (ACE_TEXT ("%s a"), argv[0]);
+ ACE_Process processa, processb;
+
+ pid_t pida = processa.spawn (options);
+ pid_t pidb = processb.spawn (options);
+
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("Spawned processes; pids %d:%d\n"),
+ pida, pidb));
+
+ if (processa.wait() == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("%p\n"),
+ ACE_TEXT ("processa wait")), -1);
+
+ if (processb.wait() == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("%p\n"),
+ ACE_TEXT ("processb wait")), -1);
+ }
+
+ return 0;
+}
+// Listing 0
diff --git a/ACE/examples/APG/Processes/Spawn.cpp b/ACE/examples/APG/Processes/Spawn.cpp
new file mode 100644
index 00000000000..0776a44a8ec
--- /dev/null
+++ b/ACE/examples/APG/Processes/Spawn.cpp
@@ -0,0 +1,206 @@
+// $Id$
+
+#include "ace/OS_NS_stdio.h"
+#include "ace/OS_NS_fcntl.h"
+#include "ace/OS_NS_pwd.h"
+#include "ace/os_include/os_pwd.h"
+#include "ace/OS_NS_stdlib.h"
+#include "ace/OS_NS_string.h"
+#include "ace/OS_NS_unistd.h"
+#include "ace/Process.h"
+#include "ace/Log_Msg.h"
+
+// Listing 1 code/ch10
+class Manager : public ACE_Process
+{
+public:
+ Manager (const ACE_TCHAR* program_name)
+ {
+ ACE_TRACE ("Manager::Manager");
+ ACE_OS::strcpy (programName_, program_name);
+ }
+
+ int doWork (void)
+ {
+ ACE_TRACE ("Manager::doWork");
+
+ // Spawn the new process; prepare() hook is called first.
+ ACE_Process_Options options;
+ pid_t pid = this->spawn (options);
+ if (pid == ACE_INVALID_PID)
+ ACE_ERROR_RETURN((LM_ERROR, ACE_TEXT ("%p\n"),
+ ACE_TEXT ("spawn")), -1);
+
+ // Wait forever for my child to exit.
+ if (this->wait () == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("%p\n"),
+ ACE_TEXT ("wait")), -1);
+
+ // Dump whatever happened.
+ this->dumpRun ();
+ return 0;
+ }
+// Listing 1
+
+private:
+ // Listing 3 code/ch10
+ int dumpRun (void)
+ {
+ ACE_TRACE ("Manager::dumpRun");
+
+ if (ACE_OS::lseek (this->outputfd_, 0, SEEK_SET) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("%p\n"),
+ ACE_TEXT ("lseek")), -1);
+
+ char buf[1024];
+ ssize_t length = 0;
+
+ // Read the contents of the error stream written
+ // by the child and print it out.
+ while ((length = ACE_OS::read (this->outputfd_,
+ buf, sizeof(buf)-1)) > 0)
+ {
+ buf[length] = 0;
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("%C\n"), buf));
+ }
+
+ ACE_OS::close (this->outputfd_);
+ return 0;
+ }
+ // Listing 3
+
+ // Listing 2 code/ch10
+ // prepare() is inherited from ACE_Process.
+ int prepare (ACE_Process_Options &options)
+ {
+ ACE_TRACE ("Manager::prepare");
+
+ options.command_line (ACE_TEXT ("%s 1"), this->programName_);
+ if (this->setStdHandles (options) == -1 ||
+ this->setEnvVariable (options) == -1)
+ return -1;
+#if !defined (ACE_WIN32) && !defined (ACE_LACKS_PWD_FUNCTIONS)
+ return this->setUserID (options);
+#else
+ return 0;
+#endif
+ }
+
+ int setStdHandles (ACE_Process_Options &options)
+ {
+ ACE_TRACE ("Manager::setStdHandles");
+
+ ACE_OS::unlink ("output.dat");
+ this->outputfd_ =
+ ACE_OS::open ("output.dat", O_RDWR | O_CREAT);
+ return options.set_handles
+ (ACE_STDIN, ACE_STDOUT, this->outputfd_);
+ }
+
+ int setEnvVariable (ACE_Process_Options &options)
+ {
+ ACE_TRACE ("Manager::setEnvVariables");
+ return options.setenv
+ (ACE_TEXT ("PRIVATE_VAR=/that/seems/to/be/it"));
+ }
+ // Listing 2
+
+#if !defined (ACE_LACKS_PWD_FUNCTIONS)
+ // Listing 10 code/ch10
+ int setUserID (ACE_Process_Options &options)
+ {
+ ACE_TRACE ("Manager::setUserID");
+ passwd* pw = ACE_OS::getpwnam ("nobody");
+ if (pw == 0)
+ return -1;
+ options.seteuid (pw->pw_uid);
+ return 0;
+ }
+ // Listing 10
+#endif /* !ACE_LACKS_PWD_FUNCTIONS */
+
+private:
+ ACE_HANDLE outputfd_;
+ ACE_TCHAR programName_[256];
+};
+
+// Listing 4 code/ch10
+class Slave
+{
+public:
+ Slave ()
+ {
+ ACE_TRACE ("Slave::Slave");
+ }
+
+ int doWork (void)
+ {
+ ACE_TRACE ("Slave::doWork");
+
+ ACE_DEBUG ((LM_INFO,
+ ACE_TEXT ("(%P) started at %T, parent is %d\n"),
+ ACE_OS::getppid ()));
+ this->showWho ();
+ ACE_DEBUG ((LM_INFO,
+ ACE_TEXT ("(%P) the private environment is %s\n"),
+ ACE_OS::getenv ("PRIVATE_VAR")));
+
+ ACE_TCHAR str[128];
+ ACE_OS::sprintf (str, ACE_TEXT ("(%d) Enter your command\n"),
+ static_cast<int>(ACE_OS::getpid ()));
+ ACE_OS::write (ACE_STDOUT, str, ACE_OS::strlen (str));
+ this->readLine (str);
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("(%P) Executed: %C\n"),
+ str));
+ return 0;
+ }
+// Listing 4
+
+ void showWho (void)
+ {
+ ACE_TRACE ("Slave::showWho");
+#if !defined (ACE_LACKS_PWD_FUNCTIONS)
+ passwd *pw = ::getpwuid (::geteuid ());
+ ACE_DEBUG ((LM_INFO,
+ ACE_TEXT ("(%P) Running this process as:%s\n"),
+ pw->pw_name));
+#endif
+ }
+
+ ACE_TCHAR* readLine (ACE_TCHAR* str)
+ {
+ ACE_TRACE ("Slave::readLine");
+
+ int i = 0;
+ while (true)
+ {
+ ssize_t retval = ACE_OS::read (ACE_STDIN, &str[i], 1);
+ if (retval > 0)
+ {
+ if (str[i] == '\n')
+ {
+ str[++i] = 0;
+ return str;
+ }
+ i++;
+ }
+ else
+ return str;
+ }
+ }
+};
+
+// Listing 0 code/ch10
+int ACE_TMAIN (int argc, ACE_TCHAR *argv[])
+{
+ if (argc > 1) // Slave mode
+ {
+ Slave s;
+ return s.doWork ();
+ }
+
+ // Else, Master mode
+ Manager m (argv[0]);
+ return m.doWork ();
+}
+// Listing 0
diff --git a/ACE/examples/APG/Processes/processes.mpc b/ACE/examples/APG/Processes/processes.mpc
new file mode 100644
index 00000000000..a7cb01040bb
--- /dev/null
+++ b/ACE/examples/APG/Processes/processes.mpc
@@ -0,0 +1,34 @@
+// -*- MPC -*-
+// $Id$
+
+project(Process Manager Death) : aceexe {
+ avoids += ace_for_tao
+ exename = Process_Manager_Death
+ Source_Files {
+ Process_Manager_Death.cpp
+ }
+}
+
+project(Process Manager Spawn) : aceexe {
+ avoids += ace_for_tao
+ exename = Process_Manager_Spawn
+ Source_Files {
+ Process_Manager_Spawn.cpp
+ }
+}
+
+project(Process Mutex) : aceexe {
+ avoids += ace_for_tao
+ exename = Process_Mutex
+ Source_Files {
+ Process_Mutex.cpp
+ }
+}
+
+project(Spawn) : aceexe {
+ avoids += ace_for_tao
+ exename = Spawn
+ Source_Files {
+ Spawn.cpp
+ }
+}
diff --git a/ACE/examples/APG/Reactor/.cvsignore b/ACE/examples/APG/Reactor/.cvsignore
new file mode 100644
index 00000000000..c2d63b45dcf
--- /dev/null
+++ b/ACE/examples/APG/Reactor/.cvsignore
@@ -0,0 +1,16 @@
+Client
+Client
+HAStatus
+HAStatus
+HAStatus-AC
+HAStatus-AC
+Reschedule
+Reschedule
+Schedule_Timers
+Schedule_Timers
+Timer_Cancel
+Timer_Cancel
+Timer_State_Data
+Timer_State_Data
+Timers
+Timers
diff --git a/ACE/examples/APG/Reactor/Client.cpp b/ACE/examples/APG/Reactor/Client.cpp
new file mode 100644
index 00000000000..b2773bbf7f3
--- /dev/null
+++ b/ACE/examples/APG/Reactor/Client.cpp
@@ -0,0 +1,118 @@
+/**
+ * $Id$
+ *
+ * A simple client program using ACE_Svc_Handler and ACE_Connector.
+ */
+
+#include "ace/OS_NS_stdio.h"
+#include "ace/OS_NS_errno.h"
+#include "ace/OS_NS_string.h"
+#include "ace/OS_NS_sys_time.h"
+#include "Client.h"
+
+// Listing 2 code/ch07
+int Client::open (void *p)
+{
+ ACE_Time_Value iter_delay (2); // Two seconds
+ if (super::open (p) == -1)
+ return -1;
+ this->notifier_.reactor (this->reactor ());
+ this->msg_queue ()->notification_strategy (&this->notifier_);
+ this->iterations_ = 0;
+ return this->reactor ()->schedule_timer
+ (this, 0, ACE_Time_Value::zero, iter_delay);
+}
+// Listing 2
+
+// Listing 3 code/ch07
+int Client::handle_input (ACE_HANDLE)
+{
+ char buf[64];
+ ssize_t recv_cnt = this->peer ().recv (buf, sizeof (buf) - 1);
+ if (recv_cnt > 0)
+ {
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("%.*C"),
+ static_cast<int> (recv_cnt),
+ buf));
+ return 0;
+ }
+
+ if (recv_cnt == 0 || ACE_OS::last_error () != EWOULDBLOCK)
+ {
+ this->reactor ()->end_reactor_event_loop ();
+ return -1;
+ }
+ return 0;
+}
+// Listing 3
+
+// Listing 4 code/ch07
+int Client::handle_timeout(const ACE_Time_Value &, const void *)
+{
+ if (++this->iterations_ >= ITERATIONS)
+ {
+ this->peer ().close_writer ();
+ return 0;
+ }
+
+ ACE_Message_Block *mb;
+ ACE_NEW_RETURN (mb, ACE_Message_Block (128), -1);
+ int nbytes = ACE_OS::sprintf
+ (mb->wr_ptr (), "Iteration %d\n", this->iterations_);
+ ACE_ASSERT (nbytes > 0);
+ mb->wr_ptr (static_cast<size_t> (nbytes));
+ this->putq (mb);
+ return 0;
+}
+// Listing 4
+
+// Listing 5 code/ch07
+int Client::handle_output (ACE_HANDLE)
+{
+ ACE_Message_Block *mb;
+ ACE_Time_Value nowait (ACE_OS::gettimeofday ());
+ while (-1 != this->getq (mb, &nowait))
+ {
+ ssize_t send_cnt =
+ this->peer ().send (mb->rd_ptr (), mb->length ());
+ if (send_cnt == -1)
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("(%P|%t) %p\n"),
+ ACE_TEXT ("send")));
+ else
+ mb->rd_ptr (static_cast<size_t> (send_cnt));
+ if (mb->length () > 0)
+ {
+ this->ungetq (mb);
+ break;
+ }
+ mb->release ();
+ }
+ if (this->msg_queue ()->is_empty ())
+ this->reactor ()->cancel_wakeup
+ (this, ACE_Event_Handler::WRITE_MASK);
+ else
+ this->reactor ()->schedule_wakeup
+ (this, ACE_Event_Handler::WRITE_MASK);
+ return 0;
+}
+// Listing 5
+
+// Listing 6 code/ch07
+int ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ ACE_INET_Addr port_to_connect (ACE_TEXT ("HAStatus"), ACE_LOCALHOST);
+ ACE_Connector<Client, ACE_SOCK_CONNECTOR> connector;
+ Client client;
+ Client *pc = &client;
+ if (connector.connect (pc, port_to_connect) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("%p\n"),
+ ACE_TEXT ("connect")), 1);
+
+ ACE_Reactor::instance ()->run_reactor_event_loop ();
+ return (0);
+}
+// Listing 6
+
+// Listing 7 code/ch07
+// Listing 7
diff --git a/ACE/examples/APG/Reactor/Client.h b/ACE/examples/APG/Reactor/Client.h
new file mode 100644
index 00000000000..9aba262151a
--- /dev/null
+++ b/ACE/examples/APG/Reactor/Client.h
@@ -0,0 +1,52 @@
+/**
+ * $Id$
+ *
+ * Sample code from The ACE Programmer's Guide,
+ * copyright 2003 Addison-Wesley. All Rights Reserved.
+ */
+
+#ifndef __CLIENT_H_
+#define __CLIENT_H_
+
+#include "ace/Synch_Traits.h"
+#include "ace/Null_Condition.h"
+#include "ace/Null_Mutex.h"
+
+// Listing 1 code/ch07
+#include "ace/Reactor.h"
+#include "ace/INET_Addr.h"
+#include "ace/SOCK_Stream.h"
+#include "ace/SOCK_Connector.h"
+#include "ace/Connector.h"
+#include "ace/Svc_Handler.h"
+#include "ace/Reactor_Notification_Strategy.h"
+
+class Client :
+ public ACE_Svc_Handler<ACE_SOCK_STREAM, ACE_NULL_SYNCH>
+{
+ typedef ACE_Svc_Handler<ACE_SOCK_STREAM, ACE_NULL_SYNCH> super;
+
+public:
+ Client () : notifier_ (0, this, ACE_Event_Handler::WRITE_MASK)
+ {}
+
+ virtual int open (void * = 0);
+
+ // Called when input is available from the client.
+ virtual int handle_input (ACE_HANDLE fd = ACE_INVALID_HANDLE);
+
+ // Called when output is possible.
+ virtual int handle_output (ACE_HANDLE fd = ACE_INVALID_HANDLE);
+
+ // Called when a timer expires.
+ virtual int handle_timeout (const ACE_Time_Value &current_time,
+ const void *act = 0);
+
+private:
+ enum { ITERATIONS = 5 };
+ int iterations_;
+ ACE_Reactor_Notification_Strategy notifier_;
+};
+// Listing 1
+
+#endif /* __CLIENT_H_ */
diff --git a/ACE/examples/APG/Reactor/ClientService.h b/ACE/examples/APG/Reactor/ClientService.h
new file mode 100644
index 00000000000..f6ac96e9286
--- /dev/null
+++ b/ACE/examples/APG/Reactor/ClientService.h
@@ -0,0 +1,40 @@
+/**
+ * $Id$
+ *
+ * Sample code from The ACE Programmer's Guide,
+ * copyright 2003 Addison-Wesley. All Rights Reserved.
+ */
+
+#ifndef __CLIENTSERVICE_H_
+#define __CLIENTSERVICE_H_
+
+#include "ace/Synch_Traits.h"
+#include "ace/Null_Condition.h"
+#include "ace/Null_Mutex.h"
+
+// Listing 3 code/ch07
+#include "ace/Message_Block.h"
+#include "ace/SOCK_Stream.h"
+#include "ace/Svc_Handler.h"
+
+class ClientService :
+ public ACE_Svc_Handler<ACE_SOCK_STREAM, ACE_NULL_SYNCH>
+{
+ typedef ACE_Svc_Handler<ACE_SOCK_STREAM, ACE_NULL_SYNCH> super;
+
+public:
+ int open (void * = 0);
+
+ // Called when input is available from the client.
+ virtual int handle_input (ACE_HANDLE fd = ACE_INVALID_HANDLE);
+
+ // Called when output is possible.
+ virtual int handle_output (ACE_HANDLE fd = ACE_INVALID_HANDLE);
+
+ // Called when this handler is removed from the ACE_Reactor.
+ virtual int handle_close (ACE_HANDLE handle,
+ ACE_Reactor_Mask close_mask);
+};
+// Listing 3
+
+#endif /* __CLIENTSERVICE_H_ */
diff --git a/ACE/examples/APG/Reactor/HAStatus-AC.cpp b/ACE/examples/APG/Reactor/HAStatus-AC.cpp
new file mode 100644
index 00000000000..c99a1c5036c
--- /dev/null
+++ b/ACE/examples/APG/Reactor/HAStatus-AC.cpp
@@ -0,0 +1,139 @@
+// $Id$
+
+#include "ace/OS_NS_errno.h"
+#include "ace/OS_NS_sys_time.h"
+#include "ace/os_include/os_netdb.h"
+#include "ClientService.h"
+
+// Listing 1 code/ch07
+#include "ace/Log_Msg.h"
+#include "ace/INET_Addr.h"
+#include "ace/SOCK_Acceptor.h"
+#include "ace/Reactor.h"
+#include "ace/Acceptor.h"
+
+typedef ACE_Acceptor<ClientService, ACE_SOCK_ACCEPTOR>
+ ClientAcceptor;
+// Listing 1
+
+// Listing 4 code/ch07
+int
+ClientService::open (void *p)
+{
+ if (super::open (p) == -1)
+ return -1;
+
+ ACE_TCHAR peer_name[MAXHOSTNAMELEN];
+ ACE_INET_Addr peer_addr;
+ if (this->peer ().get_remote_addr (peer_addr) == 0 &&
+ peer_addr.addr_to_string (peer_name, MAXHOSTNAMELEN) == 0)
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("(%P|%t) Connection from %s\n"),
+ peer_name));
+ return 0;
+}
+// Listing 4
+
+// Listing 5 code/ch07
+int
+ClientService::handle_input (ACE_HANDLE)
+{
+ const size_t INPUT_SIZE = 4096;
+ char buffer[INPUT_SIZE];
+ ssize_t recv_cnt, send_cnt;
+
+ recv_cnt = this->peer ().recv (buffer, sizeof(buffer));
+ if (recv_cnt <= 0)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("(%P|%t) Connection closed\n")));
+ return -1;
+ }
+
+ send_cnt =
+ this->peer ().send (buffer,
+ static_cast<size_t> (recv_cnt));
+ if (send_cnt == recv_cnt)
+ return 0;
+ if (send_cnt == -1 && ACE_OS::last_error () != EWOULDBLOCK)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("(%P|%t) %p\n"),
+ ACE_TEXT ("send")),
+ 0);
+ if (send_cnt == -1)
+ send_cnt = 0;
+ ACE_Message_Block *mb;
+ size_t remaining =
+ static_cast<size_t> ((recv_cnt - send_cnt));
+ ACE_NEW_RETURN (mb, ACE_Message_Block (remaining), -1);
+ mb->copy (&buffer[send_cnt], remaining);
+ int output_off = this->msg_queue ()->is_empty ();
+ ACE_Time_Value nowait (ACE_OS::gettimeofday ());
+ if (this->putq (mb, &nowait) == -1)
+ {
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("(%P|%t) %p; discarding data\n"),
+ ACE_TEXT ("enqueue failed")));
+ mb->release ();
+ return 0;
+ }
+ if (output_off)
+ return this->reactor ()->register_handler
+ (this, ACE_Event_Handler::WRITE_MASK);
+ return 0;
+}
+// Listing 5
+
+// Listing 6 code/ch07
+int
+ClientService::handle_output (ACE_HANDLE)
+{
+ ACE_Message_Block *mb;
+ ACE_Time_Value nowait (ACE_OS::gettimeofday ());
+ while (-1 != this->getq (mb, &nowait))
+ {
+ ssize_t send_cnt =
+ this->peer ().send (mb->rd_ptr (), mb->length ());
+ if (send_cnt == -1)
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("(%P|%t) %p\n"),
+ ACE_TEXT ("send")));
+ else
+ mb->rd_ptr (static_cast<size_t> (send_cnt));
+ if (mb->length () > 0)
+ {
+ this->ungetq (mb);
+ break;
+ }
+ mb->release ();
+ }
+ return (this->msg_queue ()->is_empty ()) ? -1 : 0;
+}
+// Listing 6
+
+// Listing 7 code/ch07
+int
+ClientService::handle_close (ACE_HANDLE h, ACE_Reactor_Mask mask)
+{
+ if (mask == ACE_Event_Handler::WRITE_MASK)
+ return 0;
+ return super::handle_close (h, mask);
+}
+// Listing 7
+
+// Listing 2 code/ch07
+int ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ ACE_INET_Addr port_to_listen ("HAStatus");
+ ClientAcceptor acceptor;
+ if (acceptor.open (port_to_listen) == -1)
+ return 1;
+
+ ACE_Reactor::instance ()->run_reactor_event_loop ();
+
+ return (0);
+}
+// Listing 2
+
+// Listing 8 code/ch07
+// Listing 8
diff --git a/ACE/examples/APG/Reactor/HAStatus.cpp b/ACE/examples/APG/Reactor/HAStatus.cpp
new file mode 100644
index 00000000000..fb32aa61632
--- /dev/null
+++ b/ACE/examples/APG/Reactor/HAStatus.cpp
@@ -0,0 +1,332 @@
+// $Id$
+
+#include "ace/OS_NS_sys_time.h"
+#include "ace/os_include/os_netdb.h"
+
+// Listing 1 code/ch07
+#include "ace/Auto_Ptr.h"
+#include "ace/Log_Msg.h"
+#include "ace/INET_Addr.h"
+#include "ace/SOCK_Acceptor.h"
+#include "ace/Reactor.h"
+
+class ClientAcceptor : public ACE_Event_Handler
+{
+public:
+ virtual ~ClientAcceptor ();
+
+ int open (const ACE_INET_Addr &listen_addr);
+
+ // Get this handler's I/O handle.
+ virtual ACE_HANDLE get_handle (void) const
+ { return this->acceptor_.get_handle (); }
+
+ // Called when a connection is ready to accept.
+ virtual int handle_input (ACE_HANDLE fd = ACE_INVALID_HANDLE);
+
+ // Called when this handler is removed from the ACE_Reactor.
+ virtual int handle_close (ACE_HANDLE handle,
+ ACE_Reactor_Mask close_mask);
+
+protected:
+ ACE_SOCK_Acceptor acceptor_;
+};
+// Listing 1
+
+// Listing 6 code/ch07
+#include "ace/Message_Block.h"
+#include "ace/Message_Queue.h"
+#include "ace/SOCK_Stream.h"
+#include "ace/Synch.h"
+
+class ClientService : public ACE_Event_Handler
+{
+public:
+ ACE_SOCK_Stream &peer (void) { return this->sock_; }
+
+ int open (void);
+
+ // Get this handler's I/O handle.
+ virtual ACE_HANDLE get_handle (void) const
+ { return this->sock_.get_handle (); }
+
+ // Called when input is available from the client.
+ virtual int handle_input (ACE_HANDLE fd = ACE_INVALID_HANDLE);
+
+ // Called when output is possible.
+ virtual int handle_output (ACE_HANDLE fd = ACE_INVALID_HANDLE);
+
+ // Called when this handler is removed from the ACE_Reactor.
+ virtual int handle_close (ACE_HANDLE handle,
+ ACE_Reactor_Mask close_mask);
+
+protected:
+ ACE_SOCK_Stream sock_;
+ ACE_Message_Queue<ACE_NULL_SYNCH> output_queue_;
+};
+// Listing 6
+
+// Listing 5 code/ch07
+ClientAcceptor::~ClientAcceptor ()
+{
+ this->handle_close (ACE_INVALID_HANDLE, 0);
+}
+// Listing 5
+
+// Listing 2 code/ch07
+int
+ClientAcceptor::open (const ACE_INET_Addr &listen_addr)
+{
+ if (this->acceptor_.open (listen_addr, 1) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("acceptor.open")),
+ -1);
+ return this->reactor ()->register_handler
+ (this, ACE_Event_Handler::ACCEPT_MASK);
+}
+// Listing 2
+
+// Listing 3 code/ch07
+int
+ClientAcceptor::handle_input (ACE_HANDLE)
+{
+ ClientService *client;
+ ACE_NEW_RETURN (client, ClientService, -1);
+ auto_ptr<ClientService> p (client);
+
+ if (this->acceptor_.accept (client->peer ()) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("(%P|%t) %p\n"),
+ ACE_TEXT ("Failed to accept ")
+ ACE_TEXT ("client connection")),
+ -1);
+ p.release ();
+ client->reactor (this->reactor ());
+ if (client->open () == -1)
+ client->handle_close (ACE_INVALID_HANDLE, 0);
+ return 0;
+}
+// Listing 3
+
+// Listing 4 code/ch07
+int
+ClientAcceptor::handle_close (ACE_HANDLE, ACE_Reactor_Mask)
+{
+ if (this->acceptor_.get_handle () != ACE_INVALID_HANDLE)
+ {
+ ACE_Reactor_Mask m = ACE_Event_Handler::ACCEPT_MASK |
+ ACE_Event_Handler::DONT_CALL;
+ this->reactor ()->remove_handler (this, m);
+ this->acceptor_.close ();
+ }
+ return 0;
+}
+// Listing 4
+
+// Listing 7 code/ch07
+int
+ClientService::open (void)
+{
+ ACE_TCHAR peer_name[MAXHOSTNAMELEN];
+ ACE_INET_Addr peer_addr;
+ if (this->sock_.get_remote_addr (peer_addr) == 0 &&
+ peer_addr.addr_to_string (peer_name, MAXHOSTNAMELEN) == 0)
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("(%P|%t) Connection from %s\n"),
+ peer_name));
+ return this->reactor ()->register_handler
+ (this, ACE_Event_Handler::READ_MASK);
+}
+// Listing 7
+
+// Listing 8 code/ch07
+int
+ClientService::handle_input (ACE_HANDLE)
+{
+ const size_t INPUT_SIZE = 4096;
+ char buffer[INPUT_SIZE];
+ ssize_t recv_cnt, send_cnt;
+
+ if ((recv_cnt = this->sock_.recv (buffer, sizeof(buffer))) <= 0)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("(%P|%t) Connection closed\n")));
+ return -1;
+ }
+
+ send_cnt =
+ this->sock_.send (buffer, static_cast<size_t> (recv_cnt));
+ if (send_cnt == recv_cnt)
+ return 0;
+ if (send_cnt == -1 && ACE_OS::last_error () != EWOULDBLOCK)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("(%P|%t) %p\n"),
+ ACE_TEXT ("send")),
+ 0);
+ if (send_cnt == -1)
+ send_cnt = 0;
+ ACE_Message_Block *mb;
+ size_t remaining =
+ static_cast<size_t> ((recv_cnt - send_cnt));
+ ACE_NEW_RETURN (mb, ACE_Message_Block (remaining), -1);
+ mb->copy (&buffer[send_cnt], remaining);
+ int output_off = this->output_queue_.is_empty ();
+ ACE_Time_Value nowait (ACE_OS::gettimeofday ());
+ if (this->output_queue_.enqueue_tail (mb, &nowait) == -1)
+ {
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("(%P|%t) %p; discarding data\n"),
+ ACE_TEXT ("enqueue failed")));
+ mb->release ();
+ return 0;
+ }
+ if (output_off)
+ return this->reactor ()->register_handler
+ (this, ACE_Event_Handler::WRITE_MASK);
+ return 0;
+}
+// Listing 8
+
+// Listing 9 code/ch07
+int
+ClientService::handle_output (ACE_HANDLE)
+{
+ ACE_Message_Block *mb;
+ ACE_Time_Value nowait (ACE_OS::gettimeofday ());
+ while (0 == this->output_queue_.dequeue_head
+ (mb, &nowait))
+ {
+ ssize_t send_cnt =
+ this->sock_.send (mb->rd_ptr (), mb->length ());
+ if (send_cnt == -1)
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("(%P|%t) %p\n"),
+ ACE_TEXT ("send")));
+ else
+ mb->rd_ptr (static_cast<size_t> (send_cnt));
+ if (mb->length () > 0)
+ {
+ this->output_queue_.enqueue_head (mb);
+ break;
+ }
+ mb->release ();
+ }
+ return (this->output_queue_.is_empty ()) ? -1 : 0;
+}
+// Listing 9
+
+// Listing 10 code/ch07
+int
+ClientService::handle_close (ACE_HANDLE, ACE_Reactor_Mask mask)
+{
+ if (mask == ACE_Event_Handler::WRITE_MASK)
+ return 0;
+ mask = ACE_Event_Handler::ALL_EVENTS_MASK |
+ ACE_Event_Handler::DONT_CALL;
+ this->reactor ()->remove_handler (this, mask);
+ this->sock_.close ();
+ this->output_queue_.flush ();
+ delete this;
+ return 0;
+}
+// Listing 10
+
+// Listing 12 code/ch07
+class LoopStopper : public ACE_Event_Handler
+{
+public:
+ LoopStopper (int signum = SIGINT);
+
+ // Called when object is signaled by OS.
+ virtual int handle_signal (int signum,
+ siginfo_t * = 0,
+ ucontext_t * = 0);
+};
+
+LoopStopper::LoopStopper (int signum)
+{
+ ACE_Reactor::instance ()->register_handler (signum, this);
+}
+
+int
+LoopStopper::handle_signal (int, siginfo_t *, ucontext_t *)
+{
+ ACE_Reactor::instance ()->end_reactor_event_loop ();
+ return 0;
+}
+// Listing 12
+
+// Listing 13 code/ch07
+#include "ace/Signal.h"
+
+class LogSwitcher : public ACE_Event_Handler
+{
+public:
+ LogSwitcher (int on_sig, int off_sig);
+
+ // Called when object is signaled by OS.
+ virtual int handle_signal (int signum,
+ siginfo_t * = 0,
+ ucontext_t * = 0);
+
+ // Called when an exceptional event occurs.
+ virtual int handle_exception (ACE_HANDLE fd = ACE_INVALID_HANDLE);
+
+private:
+ LogSwitcher () {}
+
+ int on_sig_; // Signal to turn logging on
+ int off_sig_; // Signal to turn logging off
+ int on_off_; // 1 == turn on, 0 == turn off
+};
+
+LogSwitcher::LogSwitcher (int on_sig, int off_sig)
+ : on_sig_ (on_sig), off_sig_ (off_sig)
+{
+ ACE_Sig_Set sigs;
+ sigs.sig_add (on_sig);
+ sigs.sig_add (off_sig);
+ ACE_Reactor::instance ()->register_handler (sigs, this);
+}
+// Listing 13
+
+// Listing 14 code/ch07
+int
+LogSwitcher::handle_signal (int signum, siginfo_t *, ucontext_t *)
+{
+ if (signum == this->on_sig_ || signum == this->off_sig_)
+ {
+ this->on_off_ = signum == this->on_sig_;
+ ACE_Reactor::instance ()->notify (this);
+ }
+ return 0;
+}
+// Listing 14
+
+// Listing 15 code/ch07
+int
+LogSwitcher::handle_exception (ACE_HANDLE)
+{
+ if (this->on_off_)
+ ACE_LOG_MSG->clr_flags (ACE_Log_Msg::SILENT);
+ else
+ ACE_LOG_MSG->set_flags (ACE_Log_Msg::SILENT);
+ return 0;
+}
+// Listing 15
+
+// Listing 11 code/ch07
+int ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ ACE_INET_Addr port_to_listen ("HAStatus");
+ ClientAcceptor acceptor;
+ acceptor.reactor (ACE_Reactor::instance ());
+ if (acceptor.open (port_to_listen) == -1)
+ return 1;
+
+ ACE_Reactor::instance ()->run_reactor_event_loop ();
+
+ return (0);
+}
+// Listing 11
diff --git a/ACE/examples/APG/Reactor/Makefile.am b/ACE/examples/APG/Reactor/Makefile.am
new file mode 100644
index 00000000000..789c0ce7785
--- /dev/null
+++ b/ACE/examples/APG/Reactor/Makefile.am
@@ -0,0 +1,139 @@
+## Process this file with automake to create Makefile.in
+##
+## $Id$
+##
+## This file was generated by MPC. Any changes made directly to
+## this file will be lost the next time it is generated.
+##
+## MPC Command:
+## /acebuilds/ACE_wrappers-repository/bin/mwc.pl -include /acebuilds/MPC/config -include /acebuilds/MPC/templates -feature_file /acebuilds/ACE_wrappers-repository/local.features -noreldefs -type automake -exclude build,Kokyu
+
+ACE_BUILDDIR = $(top_builddir)
+ACE_ROOT = $(top_srcdir)
+
+## Makefile.Client.am
+noinst_PROGRAMS = Client
+
+Client_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+Client_SOURCES = \
+ Client.cpp \
+ Client.h
+
+Client_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Makefile.HAStatus.am
+noinst_PROGRAMS += HAStatus
+
+HAStatus_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+HAStatus_SOURCES = \
+ HAStatus.cpp \
+ Client.h \
+ ClientService.h
+
+HAStatus_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Makefile.HAStatus_AC.am
+noinst_PROGRAMS += HAStatus-AC
+
+HAStatus_AC_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+HAStatus_AC_SOURCES = \
+ HAStatus-AC.cpp \
+ Client.h \
+ ClientService.h
+
+HAStatus_AC_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Makefile.Reactor_Timers.am
+noinst_PROGRAMS += Timers
+
+Timers_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+Timers_SOURCES = \
+ Timers.cpp \
+ Client.h \
+ ClientService.h
+
+Timers_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Makefile.Reschedule.am
+noinst_PROGRAMS += Reschedule
+
+Reschedule_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+Reschedule_SOURCES = \
+ Reschedule.cpp \
+ Client.h \
+ ClientService.h
+
+Reschedule_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Makefile.Schedule_Timers.am
+noinst_PROGRAMS += Schedule_Timers
+
+Schedule_Timers_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+Schedule_Timers_SOURCES = \
+ Schedule_Timers.cpp \
+ Client.h \
+ ClientService.h
+
+Schedule_Timers_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Makefile.Timer_Cancel.am
+noinst_PROGRAMS += Timer_Cancel
+
+Timer_Cancel_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+Timer_Cancel_SOURCES = \
+ Timer_Cancel.cpp \
+ Client.h \
+ ClientService.h
+
+Timer_Cancel_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Makefile.Timer_State_Data.am
+noinst_PROGRAMS += Timer_State_Data
+
+Timer_State_Data_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+Timer_State_Data_SOURCES = \
+ Timer_State_Data.cpp \
+ Client.h \
+ ClientService.h
+
+Timer_State_Data_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Clean up template repositories, etc.
+clean-local:
+ -rm -f *~ *.bak *.rpo *.sym lib*.*_pure_* core core.*
+ -rm -f gcctemp.c gcctemp so_locations *.ics
+ -rm -rf cxx_repository ptrepository ti_files
+ -rm -rf templateregistry ir.out
+ -rm -rf ptrepository SunWS_cache Templates.DB
diff --git a/ACE/examples/APG/Reactor/Reschedule.cpp b/ACE/examples/APG/Reactor/Reschedule.cpp
new file mode 100644
index 00000000000..55ce1f74143
--- /dev/null
+++ b/ACE/examples/APG/Reactor/Reschedule.cpp
@@ -0,0 +1,83 @@
+/**
+ * $Id$
+ *
+ * Changing the interval
+ */
+
+#include "ace/OS_NS_time.h"
+#include "ace/Log_Msg.h"
+#include "ace/Reactor.h"
+#include "ace/Event_Handler.h"
+
+class MyTimerHandler : public ACE_Event_Handler
+{
+public:
+ int handle_timeout (const ACE_Time_Value &current_time,
+ const void * = 0 )
+ {
+ time_t epoch = ((timespec_t)current_time).tv_sec;
+ ACE_DEBUG ((LM_INFO,
+ ACE_TEXT ("handle_timeout: %s"),
+ ACE_OS::ctime(&epoch)));
+ return 0;
+ }
+
+};
+
+// Listing 1 code/ch07
+class SigintHandler : public ACE_Event_Handler
+{
+public:
+ SigintHandler (long timerId, int currentInterval)
+ : ACE_Event_Handler(),
+ timerId_(timerId),
+ currentInterval_(currentInterval)
+ {
+ }
+
+ int handle_signal (int,
+ siginfo_t * = 0,
+ ucontext_t * = 0)
+ {
+ ACE_DEBUG ((LM_INFO,
+ ACE_TEXT ("Resetting interval of timer ")
+ ACE_TEXT ("%d to %d\n"),
+ this->timerId_,
+ ++this->currentInterval_));
+ ACE_Time_Value newInterval (this->currentInterval_);
+ ACE_Reactor::instance()->
+ reset_timer_interval (this->timerId_, newInterval);
+ return 0;
+ }
+
+private:
+ long timerId_;
+ int currentInterval_;
+};
+// Listing 1
+
+int ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ ACE_Time_Value initialDelay (3);
+ ACE_Time_Value interval (5);
+
+ // Listing 2 code/ch07
+ MyTimerHandler *handler = new MyTimerHandler ();
+
+ long timerId =
+ ACE_Reactor::instance ()->schedule_timer (handler,
+ 0,
+ initialDelay,
+ interval);
+ // Listing 2
+
+ // Listing 3 code/ch07
+ SigintHandler *handleSigint =
+ new SigintHandler (timerId, 5);
+ ACE_Reactor::instance ()->register_handler (SIGINT,
+ handleSigint);
+ // Listing 3
+
+ ACE_Reactor::instance ()->run_reactor_event_loop ();
+ return 0;
+}
diff --git a/ACE/examples/APG/Reactor/Schedule_Timers.cpp b/ACE/examples/APG/Reactor/Schedule_Timers.cpp
new file mode 100644
index 00000000000..5fa57ebfa07
--- /dev/null
+++ b/ACE/examples/APG/Reactor/Schedule_Timers.cpp
@@ -0,0 +1,65 @@
+/**
+ * $Id$
+ *
+ * Scheduling timers with the Reactor
+ */
+
+#include "ace/OS_NS_time.h"
+#include "ace/Log_Msg.h"
+#include "ace/Reactor.h"
+#include "ace/Event_Handler.h"
+
+// Listing 1 code/ch07
+class MyTimerHandler : public ACE_Event_Handler
+{
+public:
+ int handle_timeout (const ACE_Time_Value &current_time,
+ const void * = 0)
+ {
+ time_t epoch = ((timespec_t)current_time).tv_sec;
+
+ ACE_DEBUG ((LM_INFO,
+ ACE_TEXT ("handle_timeout: %s\n"),
+ ACE_OS::ctime (&epoch)));
+
+ return 0;
+ }
+};
+// Listing 1
+
+// Create a SIGINT handler so that we can exit
+// the program politely
+class SigintHandler : public ACE_Event_Handler
+{
+public:
+ int handle_signal (int signum, siginfo_t * = 0,
+ ucontext_t * = 0)
+ {
+ if (signum == SIGINT)
+ {
+ ACE_Reactor::instance ()->end_reactor_event_loop ();
+ }
+ return 0;
+ }
+};
+
+int ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ // Listing 2 code/ch07
+ MyTimerHandler * timer = new MyTimerHandler ();
+ ACE_Time_Value initialDelay (3);
+ ACE_Time_Value interval (5);
+ ACE_Reactor::instance()->schedule_timer (timer,
+ 0,
+ initialDelay,
+ interval);
+ // Listing 2
+
+ // Exclude 1
+ SigintHandler * handleExit = new SigintHandler ();
+ ACE_Reactor::instance()->register_handler (SIGINT,
+ handleExit);
+ // Exclude 1
+ ACE_Reactor::instance ()->run_reactor_event_loop ();
+ return 0;
+}
diff --git a/ACE/examples/APG/Reactor/Timer_Cancel.cpp b/ACE/examples/APG/Reactor/Timer_Cancel.cpp
new file mode 100644
index 00000000000..3e6a0f2ec61
--- /dev/null
+++ b/ACE/examples/APG/Reactor/Timer_Cancel.cpp
@@ -0,0 +1,106 @@
+/**
+ * $Id$
+ *
+ * Changing the interval and canceling
+ */
+
+#include "ace/OS_NS_time.h"
+#include "ace/Log_Msg.h"
+#include "ace/Reactor.h"
+#include "ace/Event_Handler.h"
+
+class MyTimerHandler : public ACE_Event_Handler
+{
+public:
+ int handle_timeout (const ACE_Time_Value &current_time,
+ const void * = 0)
+ {
+ time_t epoch = ((timespec_t)current_time).tv_sec;
+ ACE_DEBUG ((LM_INFO,
+ ACE_TEXT ("handle_timeout: %s"),
+ ACE_OS::ctime(&epoch)));
+ return 0;
+ }
+
+};
+
+#if !defined (ACE_LACKS_UNIX_SIGNALS)
+
+// Listing 1 code/ch07
+class SignalHandler : public ACE_Event_Handler
+{
+public:
+ SignalHandler (long timerId, int currentInterval)
+ : ACE_Event_Handler(),
+ timerId_(timerId),
+ currentInterval_(currentInterval)
+ {
+ }
+
+ int handle_signal (int sig,
+ siginfo_t * = 0,
+ ucontext_t * = 0)
+ {
+ if (sig == SIGINT)
+ {
+ ACE_DEBUG ((LM_INFO,
+ ACE_TEXT ("Resetting interval of timer ")
+ ACE_TEXT ("%d to %d\n"),
+ this->timerId_,
+ ++this->currentInterval_));
+ ACE_Time_Value newInterval (this->currentInterval_);
+ ACE_Reactor::instance ()->
+ reset_timer_interval (this->timerId_, newInterval);
+ }
+ else if (sig == SIGTSTP)
+ {
+ ACE_DEBUG ((LM_INFO,
+ ACE_TEXT ("Canceling timer %d\n"),
+ this->timerId_));
+ ACE_Reactor::instance ()->cancel_timer (this->timerId_);
+ }
+
+ return 0;
+ }
+
+private:
+ long timerId_;
+ int currentInterval_;
+};
+// Listing 1
+
+#endif /* ACE_LACKS_UNIX_SIGNALS */
+
+
+int ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ ACE_Time_Value initialDelay (3);
+ ACE_Time_Value interval (5);
+
+ // Listing 2 code/ch07
+ MyTimerHandler *handler = new MyTimerHandler ();
+ long timerId =
+ ACE_Reactor::instance ()->schedule_timer (handler,
+ 0,
+ initialDelay,
+ interval);
+ // Listing 2
+
+#if !defined (ACE_LACKS_UNIX_SIGNALS)
+
+ // Listing 3 code/ch07
+ SignalHandler *mutateTimer =
+ new SignalHandler (timerId, 5);
+ ACE_Reactor::instance ()->register_handler (SIGINT,
+ mutateTimer);
+ ACE_Reactor::instance ()->register_handler (SIGTSTP,
+ mutateTimer);
+ // Listing 3
+
+#else
+ ACE_UNUSED_ARG (timerId);
+#endif /* ACE_LACKS_UNIX_SIGNALS */
+
+ ACE_Reactor::instance ()->run_reactor_event_loop ();
+ return 0;
+}
diff --git a/ACE/examples/APG/Reactor/Timer_State_Data.cpp b/ACE/examples/APG/Reactor/Timer_State_Data.cpp
new file mode 100644
index 00000000000..215381df394
--- /dev/null
+++ b/ACE/examples/APG/Reactor/Timer_State_Data.cpp
@@ -0,0 +1,153 @@
+/**
+ * $Id$
+ *
+ * Reactor examples
+ *
+ * Timers & state data
+ */
+
+#include "ace/OS_NS_time.h"
+#include "ace/Log_Msg.h"
+#include "ace/Reactor.h"
+#include "ace/Event_Handler.h"
+
+// Listing 0 code/ch07
+class TemperatureSensor
+{
+public:
+ TemperatureSensor (const char *location)
+ : location_(location),
+ count_(0),
+ temperature_(0.0)
+ // ...
+ { }
+
+ const char *location () const
+ {
+ return this->location_;
+ }
+
+ int querySensor (void)
+ {
+ // ...
+ return ++this->count_;
+ }
+
+ float temperature (void) const
+ {
+ return this->temperature_;
+ }
+
+private:
+ const char *location_;
+ int count_;
+ float temperature_;
+ // ...
+};
+// Listing 0
+
+// Listing 1 code/ch07
+class TemperatureQueryHandler : public ACE_Event_Handler
+{
+public:
+ TemperatureQueryHandler ()
+ : ACE_Event_Handler(),
+ counter_(0),
+ averageTemperature_(0.0)
+ // ...
+ {
+ }
+
+ int handle_timeout (const ACE_Time_Value &current_time,
+ const void *arg)
+ {
+ time_t epoch = ((timespec_t)current_time).tv_sec;
+
+ const TemperatureSensor *const_sensor =
+ reinterpret_cast<const TemperatureSensor *> (arg);
+ TemperatureSensor *sensor =
+ const_cast<TemperatureSensor *> (const_sensor);
+
+ int queryCount = sensor->querySensor ();
+ this->updateAverageTemperature (sensor);
+
+ ACE_DEBUG ((LM_INFO,
+ ACE_TEXT ("%s\t")
+ ACE_TEXT ("%d/%d\t")
+ ACE_TEXT ("%.2f/%.2f\t")
+ ACE_TEXT ("%s\n"),
+ sensor->location (),
+ ++this->counter_,
+ queryCount,
+ this->averageTemperature_,
+ sensor->temperature (),
+ ACE_OS::ctime(&epoch)));
+ return 0;
+ }
+
+private:
+ void updateAverageTemperature (TemperatureSensor *)
+ {
+ // ...
+ }
+
+ int counter_;
+ float averageTemperature_;
+};
+// Listing 1
+
+// Create a SIGINT handler so that we can exit
+// the program politely
+class SigintHandler : public ACE_Event_Handler
+{
+public:
+ int handle_signal (int signum, siginfo_t * = 0,
+ ucontext_t * = 0)
+ {
+ if (signum == SIGINT)
+ {
+ ACE_Reactor::instance ()->end_reactor_event_loop ();
+ }
+ return 0;
+ }
+};
+
+int ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ // Listing 2 code/ch07
+ TemperatureQueryHandler *temperatureMonitor =
+ new TemperatureQueryHandler ();
+ // Listing 2
+
+ ACE_Time_Value initialDelay (3);
+ ACE_Time_Value intervalOne (5);
+ // Listing 3 code/ch07
+ TemperatureSensor *sensorOne =
+ new TemperatureSensor ("Kitchen");
+
+ ACE_Reactor::instance ()->schedule_timer (temperatureMonitor,
+ sensorOne,
+ initialDelay,
+ intervalOne);
+ // Listing 3
+
+ ACE_Time_Value intervalTwo (4);
+ // Listing 4 code/ch07
+ TemperatureSensor *sensorTwo =
+ new TemperatureSensor ("Foyer");
+
+ ACE_Reactor::instance ()->schedule_timer (temperatureMonitor,
+ sensorTwo,
+ initialDelay,
+ intervalTwo);
+ // Listing 4
+
+ SigintHandler *handleExit = new SigintHandler ();
+
+ ACE_Reactor::instance ()->register_handler (SIGINT,
+ handleExit);
+
+ ACE_Reactor::instance ()->run_reactor_event_loop ();
+
+ return 0;
+}
diff --git a/ACE/examples/APG/Reactor/Timers.cpp b/ACE/examples/APG/Reactor/Timers.cpp
new file mode 100644
index 00000000000..c603b86bef4
--- /dev/null
+++ b/ACE/examples/APG/Reactor/Timers.cpp
@@ -0,0 +1,81 @@
+// $Id$
+
+#include "ace/config-all.h"
+#include "ace/OS_main.h"
+
+#if !defined (ACE_LACKS_FORK)
+
+#include "ace/streams.h"
+
+#include <signal.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <time.h>
+
+typedef void (*timerTask_t)(void);
+
+// Listing 1 code/ch07
+pid_t timerTask (int initialDelay,
+ int interval,
+ timerTask_t task)
+{
+ if (initialDelay < 1 && interval < 1)
+ return -1;
+
+ pid_t pid = fork ();
+
+ if (pid < 0)
+ return -1;
+
+ if (pid > 0)
+ return pid;
+
+ if (initialDelay > 0)
+ sleep (initialDelay);
+
+ if (interval < 1)
+ return 0;
+
+ while (1)
+ {
+ (*task) ();
+ sleep (interval);
+ }
+
+ ACE_NOTREACHED (return 0);
+}
+// Listing 1
+
+// Listing 2 code/ch07
+void foo ()
+{
+ time_t now = time (0);
+ cerr << "The time is " << ctime (&now) << endl;
+}
+// Listing 2
+
+void programMainLoop (void)
+{
+ sleep (30);
+}
+
+// Listing 3 code/ch07
+int ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ pid_t timerId = timerTask (3, 5, foo);
+ programMainLoop ();
+ kill (timerId, SIGINT);
+ return 0;
+}
+// Listing 3
+
+#else
+#include <stdio.h>
+
+int ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ puts ("This very unportable example requires fork().\n");
+ return 0;
+}
+
+#endif /* ACE_LACKS_FORK */
diff --git a/ACE/examples/APG/Reactor/reactor.mpc b/ACE/examples/APG/Reactor/reactor.mpc
new file mode 100644
index 00000000000..7454f9d5c9f
--- /dev/null
+++ b/ACE/examples/APG/Reactor/reactor.mpc
@@ -0,0 +1,58 @@
+// -*- MPC -*-
+// $Id$
+
+project(Client) : aceexe {
+ exename = Client
+ Source_Files {
+ Client.cpp
+ }
+}
+
+project(HAStatus) : aceexe {
+ exename = HAStatus
+ Source_Files {
+ HAStatus.cpp
+ }
+}
+
+project(HAStatus AC) : aceexe {
+ exename = HAStatus-AC
+ Source_Files {
+ HAStatus-AC.cpp
+ }
+}
+
+project(Reschedule) : aceexe {
+ exename = Reschedule
+ Source_Files {
+ Reschedule.cpp
+ }
+}
+
+project(Schedule Timers) : aceexe {
+ exename = Schedule_Timers
+ Source_Files {
+ Schedule_Timers.cpp
+ }
+}
+
+project(Timer Cancel) : aceexe {
+ exename = Timer_Cancel
+ Source_Files {
+ Timer_Cancel.cpp
+ }
+}
+
+project(*Timers) : aceexe {
+ exename = Timers
+ Source_Files {
+ Timers.cpp
+ }
+}
+
+project(Timer State Data) : aceexe {
+ exename = Timer_State_Data
+ Source_Files {
+ Timer_State_Data.cpp
+ }
+}
diff --git a/ACE/examples/APG/Shared_Memory/.cvsignore b/ACE/examples/APG/Shared_Memory/.cvsignore
new file mode 100644
index 00000000000..4fbe7c66db3
--- /dev/null
+++ b/ACE/examples/APG/Shared_Memory/.cvsignore
@@ -0,0 +1,10 @@
+Hash_Map
+Hash_Map
+Malloc
+Malloc
+Mem_Map
+Mem_Map
+PI_Malloc
+PI_Malloc
+Pool_Growth
+Pool_Growth
diff --git a/ACE/examples/APG/Shared_Memory/Hash_Map.cpp b/ACE/examples/APG/Shared_Memory/Hash_Map.cpp
new file mode 100644
index 00000000000..b8d73e0045c
--- /dev/null
+++ b/ACE/examples/APG/Shared_Memory/Hash_Map.cpp
@@ -0,0 +1,250 @@
+// $Id$
+
+#include "ace/OS_NS_stdio.h"
+
+// Listing 1 code/ch17
+#include "ace/MMAP_Memory_Pool.h"
+#include "ace/Hash_Map_With_Allocator_T.h"
+#include "ace/Malloc_T.h"
+#include "ace/PI_Malloc.h"
+#include "ace/Process_Mutex.h"
+#include "ace/Process.h"
+
+#define BACKING_STORE "map.store"
+#define MAP_NAME "records.db"
+
+#include "Record.h"
+
+typedef ACE_Allocator_Adapter<ACE_Malloc_T <ACE_MMAP_MEMORY_POOL,
+ ACE_Process_Mutex,
+ ACE_Control_Block>
+ > ALLOCATOR;
+typedef ACE_Hash_Map_With_Allocator<int, Record> HASH_MAP;
+
+ACE_Process_Mutex coordMutex("Coord-Mutex");
+// Listing 1
+
+// Listing 2 code/ch17
+HASH_MAP* smap (ALLOCATOR *shmem_allocator)
+{
+ void *db = 0;
+ if (shmem_allocator->find (MAP_NAME, db) == 0)
+ return (HASH_MAP *) db;
+ size_t hash_table_size = sizeof (HASH_MAP);
+ void *hash_map = shmem_allocator->malloc (hash_table_size);
+ if (hash_map == 0)
+ return 0;
+ new (hash_map) HASH_MAP (hash_table_size, shmem_allocator);
+ if (shmem_allocator->bind (MAP_NAME, hash_map) == -1)
+ {
+ ACE_ERROR ((LM_ERROR, ACE_TEXT ("%p\n"),
+ ACE_TEXT ("allocate_map")));
+ shmem_allocator->remove ();
+ return 0;
+ }
+ return (HASH_MAP*)hash_map;
+}
+// Listing 2
+// Listing 6 code/ch17
+int processRecords (HASH_MAP *map, ALLOCATOR *shmem_allocator)
+{
+ ACE_TRACE ("processRecords");
+
+ size_t mapLength = map->current_size ();
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("(%P|%t) Found %d records\n\n"),
+ mapLength));
+
+ int *todelete = new int[mapLength];
+ int i = 0;
+
+ for (HASH_MAP::iterator iter = map->begin ();
+ iter != map->end ();
+ iter++)
+ {
+ int key = (*iter).ext_id_;
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("(%P|%t) [%d] Preprocessing %d:%@\n"),
+ i+1, key, &(*iter).ext_id_));
+
+ todelete[i++] = key; // Mark message for deletion.
+
+ // Illustrate the find feature of the map.
+ Record record;
+ int result = map->find (key, record, shmem_allocator);
+ if (result == -1)
+ ACE_DEBUG ((LM_ERROR,
+ ACE_TEXT ("Could not find record for %d\n"),
+ key));
+ else
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("Record name: %C|id1:%d|id2:%d\n"),
+ record.name (), record.id1(), record.id2()));
+ }
+
+ // Delete everything we processed.
+ for (int j = 0; j < i ; j++)
+ {
+ int result = map->unbind (todelete[j],
+ shmem_allocator);
+ if (result == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("Failed on key %d: %p\n"),
+ ACE_TEXT ("unbind"),
+ todelete[j]),
+ -1);
+ else
+ ACE_DEBUG ((LM_INFO,
+ ACE_TEXT ("Fully processed and removed %d\n"),
+ j));
+ }
+
+ delete [] todelete;
+
+ return 0;
+}
+// Listing 6
+// Listing 4 code/ch17
+int addRecords(HASH_MAP *map, ALLOCATOR *shmem_allocator)
+{
+ ACE_TRACE ("addRecords");
+
+ char buf[32];
+ int mapLength = static_cast<int> (map->current_size ());
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("Map has %d entries; adding 20 more\n"),
+ mapLength));
+
+ for (int i = mapLength ; i < mapLength + 20; i++)
+ {
+ ACE_OS::sprintf (buf, "%s:%d", "Record", i);
+
+ // Allocate new record on stack;
+ Record newRecord (i, i+1, buf);
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("Adding a record for %d\n"), i));
+
+ int result = map->bind (i, newRecord, shmem_allocator);
+ if (result == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("%p\n"),
+ ACE_TEXT ("bind failed")), -1);
+ }
+
+ return 0;
+}
+// Listing 4
+// Listing 5 code/ch17
+int handle_child (void)
+{
+ ACE_TRACE ("handle_child");
+
+ ACE_GUARD_RETURN (ACE_Process_Mutex, ace_mon, coordMutex, -1);
+
+ ALLOCATOR * shmem_allocator = 0;
+ ACE_MMAP_Memory_Pool_Options options
+ (ACE_DEFAULT_BASE_ADDR,
+ ACE_MMAP_Memory_Pool_Options::ALWAYS_FIXED);
+
+ ACE_NEW_RETURN (shmem_allocator,
+ ALLOCATOR (BACKING_STORE,
+ BACKING_STORE,
+ &options),
+ -1);
+
+ HASH_MAP *map = smap (shmem_allocator);
+
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("(%P|%t) Map has %d entries\n"),
+ map->current_size ()));
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("In child, map is located at %@\n"),
+ map));
+
+ processRecords (map, shmem_allocator);
+ shmem_allocator->sync ();
+ delete shmem_allocator;
+
+ return 0;
+}
+// Listing 5
+// Listing 3 code/ch17
+int handle_parent (ACE_TCHAR *cmdLine)
+{
+ ACE_TRACE ("handle_parent");
+
+ ALLOCATOR * shmem_allocator = 0;
+ ACE_MMAP_Memory_Pool_Options options
+ (ACE_DEFAULT_BASE_ADDR,
+ ACE_MMAP_Memory_Pool_Options::ALWAYS_FIXED);
+
+ ACE_NEW_RETURN
+ (shmem_allocator,
+ ALLOCATOR (BACKING_STORE, BACKING_STORE, &options),
+ -1);
+
+ HASH_MAP *map = smap (shmem_allocator);
+
+ ACE_Process processa, processb;
+ ACE_Process_Options poptions;
+ const ACE_TCHAR *args[3];
+ args[0] = cmdLine;
+ args[1] = ACE_TEXT ("a");
+ args[2] = 0;
+ poptions.command_line (args);
+ {
+ ACE_GUARD_RETURN (ACE_Process_Mutex, ace_mon,
+ coordMutex, -1);
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("(%P|%t) Map has %d entries\n"),
+ map->current_size ()));
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("In parent, map is located at %@\n"),
+ map));
+
+ // Then have the child show and eat them up.
+ processa.spawn (poptions);
+
+ // First append a few records.
+ addRecords (map, shmem_allocator);
+ }
+
+
+ {
+ ACE_GUARD_RETURN (ACE_Process_Mutex, ace_mon,
+ coordMutex, -1);
+
+ // Add a few more records..
+ addRecords (map, shmem_allocator);
+
+ // Let's see what's left.
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("(%P|%t) Parent finished adding, ")
+ ACE_TEXT ("map has %d entries\n"),
+ map->current_size ()));
+
+ // Have another child try to eat them up.
+ processb.spawn (poptions);
+ }
+
+ processa.wait ();
+ processb.wait ();
+
+ // No processes are left and we don't want to keep the data
+ // around anymore; it's now safe to remove it.
+ // !!This will remove the backing store.!!
+ shmem_allocator->remove ();
+ delete shmem_allocator;
+ return 0;
+}
+
+int ACE_TMAIN (int argc, ACE_TCHAR *argv[])
+{
+ if (argc == 1) // parent
+ ACE_ASSERT (handle_parent (argv[0]) == 0);
+ else
+ ACE_ASSERT (handle_child () == 0);
+
+ ACE_UNUSED_ARG (argv);
+ return 0;
+}
+// Listing 3
diff --git a/ACE/examples/APG/Shared_Memory/Makefile.am b/ACE/examples/APG/Shared_Memory/Makefile.am
new file mode 100644
index 00000000000..b114eb0153a
--- /dev/null
+++ b/ACE/examples/APG/Shared_Memory/Makefile.am
@@ -0,0 +1,112 @@
+## Process this file with automake to create Makefile.in
+##
+## $Id$
+##
+## This file was generated by MPC. Any changes made directly to
+## this file will be lost the next time it is generated.
+##
+## MPC Command:
+## /acebuilds/ACE_wrappers-repository/bin/mwc.pl -include /acebuilds/MPC/config -include /acebuilds/MPC/templates -feature_file /acebuilds/ACE_wrappers-repository/local.features -noreldefs -type automake -exclude build,Kokyu
+
+ACE_BUILDDIR = $(top_builddir)
+ACE_ROOT = $(top_srcdir)
+
+noinst_PROGRAMS =
+
+## Makefile.Malloc.am
+
+if !BUILD_ACE_FOR_TAO
+noinst_PROGRAMS += Malloc
+
+Malloc_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+Malloc_SOURCES = \
+ Malloc.cpp \
+ Record.h
+
+Malloc_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+endif !BUILD_ACE_FOR_TAO
+
+## Makefile.Mem_Map.am
+
+if !BUILD_ACE_FOR_TAO
+noinst_PROGRAMS += Mem_Map
+
+Mem_Map_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+Mem_Map_SOURCES = \
+ Mem_Map.cpp \
+ Record.h
+
+Mem_Map_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+endif !BUILD_ACE_FOR_TAO
+
+## Makefile.PI_Malloc.am
+
+if !BUILD_ACE_FOR_TAO
+noinst_PROGRAMS += PI_Malloc
+
+PI_Malloc_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+PI_Malloc_SOURCES = \
+ PI_Malloc.cpp \
+ Record.h
+
+PI_Malloc_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+endif !BUILD_ACE_FOR_TAO
+
+## Makefile.Pool_Growth.am
+
+if !BUILD_ACE_FOR_TAO
+noinst_PROGRAMS += Pool_Growth
+
+Pool_Growth_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+Pool_Growth_SOURCES = \
+ Pool_Growth.cpp \
+ Record.h
+
+Pool_Growth_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+endif !BUILD_ACE_FOR_TAO
+
+## Makefile.Shared_Memory_Hash_Map.am
+
+if !BUILD_ACE_FOR_TAO
+noinst_PROGRAMS += Hash_Map
+
+Hash_Map_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+Hash_Map_SOURCES = \
+ Hash_Map.cpp \
+ Record.h
+
+Hash_Map_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+endif !BUILD_ACE_FOR_TAO
+
+## Clean up template repositories, etc.
+clean-local:
+ -rm -f *~ *.bak *.rpo *.sym lib*.*_pure_* core core.*
+ -rm -f gcctemp.c gcctemp so_locations *.ics
+ -rm -rf cxx_repository ptrepository ti_files
+ -rm -rf templateregistry ir.out
+ -rm -rf ptrepository SunWS_cache Templates.DB
diff --git a/ACE/examples/APG/Shared_Memory/Malloc.cpp b/ACE/examples/APG/Shared_Memory/Malloc.cpp
new file mode 100644
index 00000000000..7f1ef3a3579
--- /dev/null
+++ b/ACE/examples/APG/Shared_Memory/Malloc.cpp
@@ -0,0 +1,113 @@
+// $Id$
+
+#include "ace/OS_NS_stdio.h"
+#include "ace/OS_NS_string.h"
+
+// Listing 1 code/ch17
+#include "ace/MMAP_Memory_Pool.h"
+#include "ace/Malloc_T.h"
+#include "ace/Null_Mutex.h"
+
+typedef ACE_Malloc<ACE_MMAP_MEMORY_POOL, ACE_Null_Mutex>
+ ALLOCATOR;
+typedef ACE_Malloc_LIFO_Iterator <ACE_MMAP_MEMORY_POOL,
+ ACE_Null_Mutex>
+ MALLOC_LIFO_ITERATOR;
+
+ALLOCATOR *g_allocator;
+// Listing 1
+
+// Listing 2 code/ch17
+class Record
+{
+public:
+ Record (int id1, int id2, char *name)
+ : id1_(id1), id2_(id2), name_(0)
+ {
+ size_t len = ACE_OS::strlen (name) + 1;
+ this->name_ =
+ reinterpret_cast<char *> (g_allocator->malloc (len));
+ ACE_OS::strcpy (this->name_, name);
+ }
+
+ ~Record () { g_allocator->free (name_); }
+ char* name(void) { return name_; }
+ int id1 (void) { return id1_; }
+ int id2 (void) { return id2_; }
+
+private:
+ int id1_;
+ int id2_;
+ char *name_;
+};
+// Listing 2
+// Listing 5 code/ch17
+void showRecords ()
+{
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("The following records were found:\n")));
+ {
+ MALLOC_LIFO_ITERATOR iter (*g_allocator);
+
+ for (void *temp = 0; iter.next (temp) != 0; iter.advance ())
+ {
+ Record *record =
+ reinterpret_cast<Record *> (temp);
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("Record name: %C|id1:%d|id2:%d\n"),
+ record->name (),
+ record->id1 (),
+ record->id2 ()));
+ }
+ }
+}
+// Listing 5
+// Listing 3 code/ch17
+int addRecords ()
+{
+ char buf[32];
+
+ for (int i = 0; i < 10; i++)
+ {
+ ACE_OS::sprintf (buf, "%s:%d", "Record", i);
+ void *memory = g_allocator->malloc (sizeof (Record));
+ if (memory == 0)
+ ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("%p\n"),
+ ACE_TEXT ("Unable to malloc")),
+ -1);
+
+ // Allocate and place record
+ Record* newRecord = new (memory) Record (i, i+1, buf);
+ if (g_allocator->bind (buf, newRecord) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("%p\n"),
+ ACE_TEXT ("bind failed")),
+ -1);
+ }
+
+ return 0;
+}
+// Listing 3
+// Listing 4 code/ch17
+// Backing file where the data is kept.
+#define BACKING_STORE ACE_TEXT("backing.store")
+
+int ACE_TMAIN (int argc, ACE_TCHAR *[])
+{
+ ACE_NEW_RETURN (g_allocator,
+ ALLOCATOR (BACKING_STORE),
+ -1);
+ if (argc > 1)
+ {
+ showRecords ();
+ }
+ else
+ {
+ addRecords ();
+ }
+
+ g_allocator->sync ();
+ delete g_allocator;
+ return 0;
+}
+// Listing 4
+
diff --git a/ACE/examples/APG/Shared_Memory/Mem_Map.cpp b/ACE/examples/APG/Shared_Memory/Mem_Map.cpp
new file mode 100644
index 00000000000..c96cd0b0f45
--- /dev/null
+++ b/ACE/examples/APG/Shared_Memory/Mem_Map.cpp
@@ -0,0 +1,35 @@
+// $Id$
+
+#include "ace/OS_NS_fcntl.h"
+#include "ace/OS_NS_string.h"
+#include "ace/Mem_Map.h"
+#include "ace/Log_Msg.h"
+
+// Listing 1 code/ch17
+int ACE_TMAIN (int, ACE_TCHAR *argv[])
+{
+ ACE_HANDLE srcHandle = ACE_OS::open (argv[1], O_RDONLY);
+ ACE_ASSERT(srcHandle != ACE_INVALID_HANDLE);
+
+ ACE_Mem_Map srcMap (srcHandle, -1, PROT_READ, ACE_MAP_PRIVATE);
+ ACE_ASSERT(srcMap.addr () != 0);
+
+ ACE_Mem_Map destMap (argv[2],
+ srcMap.size (),
+ O_RDWR | O_CREAT,
+ ACE_DEFAULT_FILE_PERMS,
+ PROT_RDWR,
+ ACE_MAP_SHARED);
+ ACE_ASSERT(destMap.addr () != 0);
+
+ ACE_OS::memcpy (destMap.addr (),
+ srcMap.addr (),
+ srcMap.size ());
+ destMap.sync ();
+
+ srcMap.close ();
+ destMap.close ();
+ return 0;
+}
+// Listing 1
+
diff --git a/ACE/examples/APG/Shared_Memory/PI_Malloc.cpp b/ACE/examples/APG/Shared_Memory/PI_Malloc.cpp
new file mode 100644
index 00000000000..2d31ba96f35
--- /dev/null
+++ b/ACE/examples/APG/Shared_Memory/PI_Malloc.cpp
@@ -0,0 +1,140 @@
+// $Id$
+
+#include "ace/OS_NS_stdio.h"
+#include "ace/OS_NS_string.h"
+
+// Listing 1 code/ch17
+#include "ace/MMAP_Memory_Pool.h"
+#include "ace/Malloc_T.h"
+#include "ace/Null_Mutex.h"
+#include "ace/PI_Malloc.h"
+
+typedef ACE_Malloc_T <ACE_MMAP_MEMORY_POOL,
+ ACE_Null_Mutex,
+ ACE_PI_Control_Block>
+ ALLOCATOR;
+typedef ACE_Malloc_LIFO_Iterator_T<ACE_MMAP_MEMORY_POOL,
+ ACE_Null_Mutex,
+ ACE_PI_Control_Block>
+ MALLOC_LIFO_ITERATOR;
+
+ALLOCATOR *g_allocator;
+// Listing 1
+// Listing 2 code/ch17
+class Record
+{
+public:
+ Record (int id1, int id2, char *name)
+ : id1_(id1), id2_(id2)
+ {
+ size_t len = ACE_OS::strlen (name) + 1;
+ char *buf =
+ reinterpret_cast<char *> (g_allocator->malloc (len));
+ ACE_OS::strcpy (buf, name);
+ name_ = buf;
+ }
+
+ ~Record() { g_allocator->free (name_.addr ()); }
+
+ char *name (void) { return name_; }
+ int id1 (void) { return id1_; }
+ int id2 (void) { return id2_; }
+
+private:
+ int id1_;
+ int id2_;
+ ACE_Based_Pointer_Basic<char> name_;
+};
+// Listing 2
+
+void showRecords (void)
+{
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("The following records were found:\n")));
+
+ {
+ MALLOC_LIFO_ITERATOR iter (*g_allocator);
+
+ for (void *temp = 0; iter.next (temp) != 0; iter.advance ())
+ {
+ Record *record =
+ reinterpret_cast<Record *> (temp);
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("Record name: %C|id1:%d|id2:%d\n"),
+ record->name(), record->id1(), record->id2()));
+ }
+ }
+}
+
+int addRecords (void)
+{
+ char buf[32];
+
+ for (int i = 0; i < 10; i++)
+ {
+ ACE_OS::sprintf (buf, "%s:%d", "Record", i);
+
+ void *memory = g_allocator->malloc (sizeof (Record));
+ if (memory == NULL)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("Unable to malloc")),
+ -1);
+
+ // Allocate and place record
+ Record* newRecord = new (memory) Record (i, i+1, buf);
+ if (g_allocator->bind (buf, newRecord) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("bind failed")),
+ -1);
+ }
+
+ return 0;
+}
+
+// Listing 3 code/ch17
+// Backing file where the data is kept.
+#define BACKING_STORE ACE_TEXT("backing2.store")
+
+int ACE_TMAIN (int argc, ACE_TCHAR *[])
+{
+ if (argc > 1)
+ {
+ ACE_MMAP_Memory_Pool_Options options
+ (ACE_DEFAULT_BASE_ADDR,
+ ACE_MMAP_Memory_Pool_Options::ALWAYS_FIXED);
+ ACE_NEW_RETURN (g_allocator,
+ ALLOCATOR (BACKING_STORE,
+ BACKING_STORE,
+ &options),
+ -1);
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("Mapped to base address %@\n"),
+ g_allocator->base_addr ()));
+
+ showRecords ();
+ }
+ else
+ {
+ ACE_MMAP_Memory_Pool_Options options
+ (0, ACE_MMAP_Memory_Pool_Options::NEVER_FIXED);
+ ACE_NEW_RETURN (g_allocator,
+ ALLOCATOR (BACKING_STORE,
+ BACKING_STORE,
+ &options),
+ -1);
+
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("Mapped to base address %@\n"),
+ g_allocator->base_addr ()));
+
+ addRecords();
+ }
+
+ g_allocator->sync ();
+ delete g_allocator;
+ return 0;
+}
+// Listing 3
+
diff --git a/ACE/examples/APG/Shared_Memory/Pool_Growth.cpp b/ACE/examples/APG/Shared_Memory/Pool_Growth.cpp
new file mode 100644
index 00000000000..c354b098242
--- /dev/null
+++ b/ACE/examples/APG/Shared_Memory/Pool_Growth.cpp
@@ -0,0 +1,261 @@
+// $Id$
+
+#include "ace/OS_NS_stdio.h"
+#include "ace/OS_NS_unistd.h"
+#include "ace/Malloc_T.h"
+#include "ace/PI_Malloc.h"
+#include "ace/Process_Mutex.h"
+#include "ace/Process.h"
+#include "ace/Unbounded_Queue.h"
+#include "ace/MMAP_Memory_Pool.h"
+
+#define BACKING_STORE "queue.dat"
+#define QUEUE_NAME "queue.db"
+
+typedef ACE_Allocator_Adapter<ACE_Malloc <ACE_MMAP_MEMORY_POOL, ACE_Process_Mutex> > ALLOCATOR;
+
+ACE_Process_Mutex coordMutex("Coord-Mutex");
+
+// Listing 1 code/ch17
+template <class T>
+class Unbounded_Queue : public ACE_Unbounded_Queue<T>
+{
+public:
+ typedef ACE_Unbounded_Queue<T> BASE;
+
+ Unbounded_Queue(ACE_Allocator* allocator)
+ : ACE_Unbounded_Queue<T> (allocator)
+ { }
+
+ int enqueue_tail (const T &new_item, ACE_Allocator* allocator)
+ {
+ this->allocator_ = allocator;
+ return BASE::enqueue_tail (new_item);
+ }
+
+ int dequeue_head (T &item, ACE_Allocator* allocator)
+ {
+ this->allocator_ = allocator;
+ return BASE::dequeue_head (item);
+ }
+
+ void delete_nodes (ACE_Allocator* allocator)
+ {
+ this->allocator_ = allocator;
+ delete_nodes ();
+ }
+};
+// Listing 1
+
+#include "Record.h"
+
+typedef Unbounded_Queue<Record> QUEUE;
+
+QUEUE* squeue(ALLOCATOR* shmem_allocator)
+{
+ void *queue = 0;
+
+ // This is the easy case since if we find hash table in the
+ // memory-mapped file we know it's already initialized.
+ if (shmem_allocator->find (QUEUE_NAME, queue) == 0)
+ return (QUEUE *) queue;
+
+ // Create a new map (because we've just created a new
+ // memory-mapped file).
+ size_t queue_size = sizeof (QUEUE);
+
+ queue = shmem_allocator->malloc (queue_size);
+
+ // If allocation failed ...
+ if (queue == 0)
+ return 0;
+
+ new (queue) QUEUE (shmem_allocator);
+
+ if (shmem_allocator->bind (QUEUE_NAME, queue) == -1)
+ {
+ // Attempt to clean up.
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("squeue bind\n")));
+ shmem_allocator->remove();
+
+ return 0;
+ }
+
+ return (QUEUE*)queue;
+}
+
+static ALLOCATOR * g_shmem_allocator = 0;
+
+// Listing 4 code/ch17
+int processRecord (ALLOCATOR *shmem_allocator)
+{
+ ACE_GUARD_RETURN (ACE_Process_Mutex, ace_mon, coordMutex, -1);
+
+ QUEUE* queue = squeue (shmem_allocator);
+ if (queue == 0)
+ {
+ delete shmem_allocator;
+ ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("%p\n"),
+ ACE_TEXT ("Could not obtain queue")),
+ -1);
+ }
+
+ if (queue->is_empty ()) // Check for anything to process.
+ return 0;
+
+ Record record;
+ if (queue->dequeue_head (record, shmem_allocator) == -1)
+ {
+ ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("%p\n"),
+ ACE_TEXT ("dequeue_head\n")),
+ -1);
+ }
+
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("(%P|%t) Processing record|name: %C")
+ ACE_TEXT ("|Record id1:%d|Record id2:%d\n"),
+ record.name (), record.id1 (), record.id2 ()));
+ if (record.id1 () == -1)
+ queue->enqueue_tail (record, shmem_allocator);
+ return record.id1 ();
+}
+// Listing 4
+// Listing 5 code/ch17
+#if defined(WIN32)
+
+int handle_remap (EXCEPTION_POINTERS *ep)
+{
+ ACE_DEBUG ((LM_INFO, ACE_TEXT ("Handle a remap\n")));
+
+ DWORD ecode = ep->ExceptionRecord->ExceptionCode;
+ if (ecode != EXCEPTION_ACCESS_VIOLATION)
+ return EXCEPTION_CONTINUE_SEARCH;
+
+ void *addr =
+ (void *) ep->ExceptionRecord->ExceptionInformation[1];
+ if (g_shmem_allocator->alloc().memory_pool().remap (addr) == -1)
+ return EXCEPTION_CONTINUE_SEARCH;
+#if __X86__
+ // This is 80x86-specific.
+ ep->ContextRecord->Edi = (DWORD) addr;
+#elif __MIPS__
+ ep->ContextRecord->IntA0 =
+ ep->ContextRecord->IntV0 = (DWORD) addr;
+ ep->ContextRecord->IntT5 =
+ ep->ContextRecord->IntA0 + 3;
+#endif /* __X86__ */
+
+ return EXCEPTION_CONTINUE_EXECUTION;
+}
+
+int processWin32Record (ALLOCATOR *shmem_allocator)
+{
+ ACE_SEH_TRY
+ {
+ return processRecord (shmem_allocator);
+ }
+
+ ACE_SEH_EXCEPT (handle_remap (GetExceptionInformation ()))
+ { }
+
+ return 0;
+}
+#endif /*WIN32*/
+// Listing 5
+
+int sendRecord (int recordId, ALLOCATOR *shmem_allocator)
+{
+ ACE_GUARD_RETURN (ACE_Process_Mutex, ace_mon, coordMutex, -1);
+
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("(%P|%t) Sending record %d\n"),
+ recordId));
+
+ QUEUE * queue = squeue (shmem_allocator);
+ char buf[128];
+ ACE_OS::sprintf (buf, "%s:%d", "Record", recordId);
+ Record newRecord (recordId, recordId+1, buf);
+
+ int result = queue->enqueue_tail (newRecord, shmem_allocator);
+ if (result == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("%p\n"),
+ ACE_TEXT ("enqueue failed\n")),
+ -1);
+ return 0;
+}
+
+// Listing 2 code/ch17
+int handle_parent (ACE_TCHAR *cmdLine)
+{
+ ALLOCATOR *shmem_allocator = 0;
+ ACE_MMAP_Memory_Pool_Options options
+ (ACE_DEFAULT_BASE_ADDR,
+ ACE_MMAP_Memory_Pool_Options::ALWAYS_FIXED);
+
+ // Create the allocator.
+ ACE_NEW_RETURN (shmem_allocator,
+ ALLOCATOR (BACKING_STORE,
+ BACKING_STORE,
+ &options),
+ -1);
+
+ ACE_Process processa, processb;
+ ACE_Process_Options poptions;
+ const ACE_TCHAR *args[3];
+ args[0] = cmdLine;
+ args[1] = ACE_TEXT ("a");
+ args[2] = 0;
+ poptions.command_line (args);
+ processa.spawn (poptions);
+ processb.spawn (poptions);
+
+ // Make sure the child does map a partial pool in memory.
+ ACE_OS::sleep (2);
+
+ for (int i = 0; i < 100; i++)
+ sendRecord (i, shmem_allocator);
+ sendRecord (-1, shmem_allocator);
+
+ processa.wait ();
+ processb.wait ();
+ shmem_allocator->remove ();
+ return 0;
+}
+// Listing 2
+
+// Listing 3 code/ch17
+int handle_child (void)
+{
+ ALLOCATOR *shmem_allocator = 0;
+ ACE_MMAP_Memory_Pool_Options options
+ (ACE_DEFAULT_BASE_ADDR,
+ ACE_MMAP_Memory_Pool_Options::ALWAYS_FIXED);
+ ACE_NEW_RETURN (shmem_allocator,
+ ALLOCATOR (BACKING_STORE,
+ BACKING_STORE,
+ &options),
+ -1);
+ g_shmem_allocator = shmem_allocator;
+
+#if defined (WIN32)
+ while (processWin32Record (shmem_allocator) != -1)
+ ;
+#else
+ while (processRecord (shmem_allocator) != -1)
+ ;
+#endif
+ return 0;
+}
+// Listing 3
+
+int ACE_TMAIN (int argc, ACE_TCHAR *argv[])
+{
+ if (argc == 1)
+ handle_parent(argv[0]);
+ else
+ handle_child();
+
+ return 0;
+}
+
diff --git a/ACE/examples/APG/Shared_Memory/Record.h b/ACE/examples/APG/Shared_Memory/Record.h
new file mode 100644
index 00000000000..f3a63e1298b
--- /dev/null
+++ b/ACE/examples/APG/Shared_Memory/Record.h
@@ -0,0 +1,45 @@
+/**
+ * $Id$
+ *
+ * Sample code from The ACE Programmer's Guide,
+ * copyright 2003 Addison-Wesley. All Rights Reserved.
+ */
+
+#ifndef __RECORD_H_
+#define __RECORD_H_
+
+#include "ace/OS_NS_string.h"
+#include "ace/Based_Pointer_T.h"
+
+// Listing 11 code/ch17
+class Record
+{
+public:
+ Record () { }
+ ~Record () { }
+
+ Record (const Record& rec)
+ : id1_(rec.id1_), id2_(rec.id2_)
+ {
+ ACE_OS::strcpy (recName_, rec.name_);
+ this->name_ = recName_;
+ }
+ Record (int id1, int id2, char *name)
+ : id1_(id1), id2_(id2)
+ {
+ ACE_OS::strcpy (recName_, name);
+ this->name_ = recName_;
+ }
+ char *name (void) { return recName_; }
+ int id1 (void) { return id1_; }
+ int id2 (void) { return id2_; }
+
+private:
+ int id1_;
+ int id2_;
+ char recName_[128];
+ ACE_Based_Pointer_Basic<char> name_;
+};
+// Listing 11
+
+#endif /* __RECORD_H_ */
diff --git a/ACE/examples/APG/Shared_Memory/shared_memory.mpc b/ACE/examples/APG/Shared_Memory/shared_memory.mpc
new file mode 100644
index 00000000000..2cf2400ef8e
--- /dev/null
+++ b/ACE/examples/APG/Shared_Memory/shared_memory.mpc
@@ -0,0 +1,42 @@
+// -*- MPC -*-
+// $Id$
+
+project(*Hash Map) : aceexe {
+ avoids += ace_for_tao
+ exename = Hash_Map
+ Source_Files {
+ Hash_Map.cpp
+ }
+}
+
+project(Malloc) : aceexe {
+ avoids += ace_for_tao
+ exename = Malloc
+ Source_Files {
+ Malloc.cpp
+ }
+}
+
+project(Mem Map) : aceexe {
+ avoids += ace_for_tao
+ exename = Mem_Map
+ Source_Files {
+ Mem_Map.cpp
+ }
+}
+
+project(PI Malloc) : aceexe {
+ avoids += ace_for_tao
+ exename = PI_Malloc
+ Source_Files {
+ PI_Malloc.cpp
+ }
+}
+
+project(Pool Growth) : aceexe {
+ avoids += ace_for_tao
+ exename = Pool_Growth
+ Source_Files {
+ Pool_Growth.cpp
+ }
+}
diff --git a/ACE/examples/APG/Signals/.cvsignore b/ACE/examples/APG/Signals/.cvsignore
new file mode 100644
index 00000000000..23774a5d6a0
--- /dev/null
+++ b/ACE/examples/APG/Signals/.cvsignore
@@ -0,0 +1,10 @@
+SigAction
+SigAction
+SigGuard
+SigGuard
+SigHandler
+SigHandler
+SigHandlers
+SigHandlers
+SigInfo
+SigInfo
diff --git a/ACE/examples/APG/Signals/Makefile.am b/ACE/examples/APG/Signals/Makefile.am
new file mode 100644
index 00000000000..ffc67bdd0f0
--- /dev/null
+++ b/ACE/examples/APG/Signals/Makefile.am
@@ -0,0 +1,85 @@
+## Process this file with automake to create Makefile.in
+##
+## $Id$
+##
+## This file was generated by MPC. Any changes made directly to
+## this file will be lost the next time it is generated.
+##
+## MPC Command:
+## /acebuilds/ACE_wrappers-repository/bin/mwc.pl -include /acebuilds/MPC/config -include /acebuilds/MPC/templates -feature_file /acebuilds/ACE_wrappers-repository/local.features -noreldefs -type automake -exclude build,Kokyu
+
+ACE_BUILDDIR = $(top_builddir)
+ACE_ROOT = $(top_srcdir)
+
+## Makefile.SigAction.am
+noinst_PROGRAMS = SigAction
+
+SigAction_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+SigAction_SOURCES = \
+ SigAction.cpp
+
+SigAction_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Makefile.SigGuard.am
+noinst_PROGRAMS += SigGuard
+
+SigGuard_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+SigGuard_SOURCES = \
+ SigGuard.cpp
+
+SigGuard_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Makefile.SigHandler.am
+noinst_PROGRAMS += SigHandler
+
+SigHandler_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+SigHandler_SOURCES = \
+ SigHandler.cpp
+
+SigHandler_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Makefile.SigHandlers.am
+noinst_PROGRAMS += SigHandlers
+
+SigHandlers_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+SigHandlers_SOURCES = \
+ SigHandlers.cpp
+
+SigHandlers_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Makefile.SigInfo.am
+noinst_PROGRAMS += SigInfo
+
+SigInfo_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+SigInfo_SOURCES = \
+ SigInfo.cpp
+
+SigInfo_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Clean up template repositories, etc.
+clean-local:
+ -rm -f *~ *.bak *.rpo *.sym lib*.*_pure_* core core.*
+ -rm -f gcctemp.c gcctemp so_locations *.ics
+ -rm -rf cxx_repository ptrepository ti_files
+ -rm -rf templateregistry ir.out
+ -rm -rf ptrepository SunWS_cache Templates.DB
diff --git a/ACE/examples/APG/Signals/SigAction.cpp b/ACE/examples/APG/Signals/SigAction.cpp
new file mode 100644
index 00000000000..6d818ae9400
--- /dev/null
+++ b/ACE/examples/APG/Signals/SigAction.cpp
@@ -0,0 +1,75 @@
+// $Id$
+
+#include "ace/OS_NS_unistd.h"
+#include "ace/OS_NS_stdlib.h"
+#include "ace/Log_Msg.h"
+// Listing 1 code/ch11
+#include "ace/Signal.h"
+
+// Forward declaration.
+static void register_actions ();
+
+int ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ ACE_TRACE (ACE_TEXT ("::main"));
+
+ ::register_actions (); // Register actions to happen.
+
+ // This will be raised immediately.
+ ACE_OS::kill (ACE_OS::getpid(), SIGUSR2);
+
+ // This will pend until the first signal is completely
+ // handled and returns, because we masked it out
+ // in the registerAction call.
+ ACE_OS::kill (ACE_OS::getpid (), SIGUSR1);
+
+ while (ACE_OS::sleep (100) == -1)
+ {
+ if (errno == EINTR)
+ continue;
+ else
+ ACE_OS::exit (1);
+ }
+ return 0;
+}
+// Listing 1
+#if defined (ACE_HAS_SIG_C_FUNC)
+extern "C" {
+#endif
+// Listing 3 code/ch11
+static void my_sighandler (int signo)
+{
+ ACE_TRACE (ACE_TEXT ("::my_sighandler"));
+
+ ACE_OS::kill (ACE_OS::getpid (), SIGUSR1);
+
+ if (signo == SIGUSR1)
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Signal SIGUSR1\n")));
+ else
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Signal SIGUSR2\n")));
+
+ ACE_OS::sleep (10);
+}
+#if defined (ACE_HAS_SIG_C_FUNC)
+}
+#endif
+// Listing 3
+// Listing 2 code/ch11
+static void register_actions ()
+{
+ ACE_TRACE (ACE_TEXT ("::register_actions"));
+
+ ACE_Sig_Action sa (reinterpret_cast <ACE_SignalHandler> (my_sighandler));
+
+ // Make sure we specify that SIGUSR1 will be masked out
+ // during the signal handler's execution.
+ ACE_Sig_Set ss;
+ ss.sig_add (SIGUSR1);
+ sa.mask (ss);
+
+ // Register the same handler function for these
+ // two signals.
+ sa.register_action (SIGUSR1);
+ sa.register_action (SIGUSR2);
+}
+// Listing 2
diff --git a/ACE/examples/APG/Signals/SigGuard.cpp b/ACE/examples/APG/Signals/SigGuard.cpp
new file mode 100644
index 00000000000..679af032904
--- /dev/null
+++ b/ACE/examples/APG/Signals/SigGuard.cpp
@@ -0,0 +1,43 @@
+// $Id$
+
+#include "ace/OS_NS_unistd.h"
+#include "ace/Log_Msg.h"
+#include "ace/Signal.h"
+#include "ace/Sig_Handler.h"
+
+// Listing 1
+class MySignalHandler : public ACE_Event_Handler
+ {
+ public:
+ virtual int handle_signal(int signo,
+ siginfo_t * = 0, ucontext_t * = 0)
+ {
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Signal %d\n"), signo));
+ return 0;
+ }
+ };
+
+int ACE_TMAIN (int, ACE_TCHAR *[])
+{
+
+ MySignalHandler sighandler;
+ ACE_Sig_Handler sh;
+ sh.register_handler (SIGUSR1, &sighandler);
+
+ ACE_Sig_Set ss;
+ ss.sig_add (SIGUSR1);
+
+ ACE_Sig_Guard guard (&ss);
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("Entering critical region\n")));
+ ACE_OS::sleep (10);
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("Leaving critical region\n")));
+ }
+
+ // Do other stuff.
+
+ return 0;
+}
+// Listing 1
diff --git a/ACE/examples/APG/Signals/SigHandler.cpp b/ACE/examples/APG/Signals/SigHandler.cpp
new file mode 100644
index 00000000000..b7068c9dea6
--- /dev/null
+++ b/ACE/examples/APG/Signals/SigHandler.cpp
@@ -0,0 +1,60 @@
+// $Id$
+
+#include "ace/OS_NS_unistd.h"
+#include "ace/Log_Msg.h"
+#include "ace/Signal.h"
+#include "ace/Sig_Handler.h"
+
+// Listing 1 code/ch11
+class MySignalHandler : public ACE_Event_Handler
+{
+public:
+ MySignalHandler (int signum) : signum_(signum)
+ { }
+
+ virtual ~MySignalHandler()
+ { }
+
+ virtual int handle_signal (int signum,
+ siginfo_t * = 0,
+ ucontext_t * = 0)
+ {
+ ACE_TRACE (ACE_TEXT ("MySignalHandler::handle_signal"));
+
+ // Make sure the right handler was called back.
+ ACE_ASSERT (signum == this->signum_);
+
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("%S occured\n"), signum));
+ return 0;
+ }
+
+private:
+ int signum_;
+};
+// Listing 1
+// Listing 2 code/ch11
+int ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ MySignalHandler h1 (SIGUSR1), h2 (SIGUSR2);
+ ACE_Sig_Handler handler;
+ handler.register_handler (SIGUSR1, &h1);
+ handler.register_handler (SIGUSR2, &h2);
+
+ ACE_OS::kill (ACE_OS::getpid (), SIGUSR1);
+ ACE_OS::kill (ACE_OS::getpid (), SIGUSR2);
+
+ int time = 10;
+ while ((time = ACE_OS::sleep (time)) == -1)
+ {
+ if (errno == EINTR)
+ continue;
+ else
+ {
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("sleep")), -1);
+ }
+ }
+ return 0;
+}
+// Listing 2
diff --git a/ACE/examples/APG/Signals/SigHandlers.cpp b/ACE/examples/APG/Signals/SigHandlers.cpp
new file mode 100644
index 00000000000..19634b50d72
--- /dev/null
+++ b/ACE/examples/APG/Signals/SigHandlers.cpp
@@ -0,0 +1,54 @@
+// $Id$
+
+#include "ace/OS_NS_unistd.h"
+#include "ace/Log_Msg.h"
+#include "ace/Signal.h"
+#include "ace/Sig_Handler.h"
+
+class MySignalHandler : public ACE_Event_Handler
+{
+public:
+ MySignalHandler (int signum) : signum_(signum)
+ { }
+
+ virtual ~MySignalHandler ()
+ { }
+
+ virtual int handle_signal (int signum, siginfo_t * = 0, ucontext_t * = 0)
+ {
+ ACE_TRACE (ACE_TEXT ("MySignalHandler::handle_signal"));
+
+ // Make sure the right handler was called back..
+ ACE_ASSERT(signum == this->signum_);
+
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("%d occured\n"), signum));
+
+ return 0;
+ }
+
+private:
+ int signum_;
+};
+
+// Listing 1 code/ch11
+int ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ MySignalHandler h1 (SIGUSR1), h2 (SIGUSR1);
+ ACE_Sig_Handlers handler;
+ handler.register_handler (SIGUSR1, &h1);
+ handler.register_handler (SIGUSR1, &h2);
+
+ ACE_OS::kill (ACE_OS::getpid (), SIGUSR1);
+
+ int time = 10;
+ while ((time = ACE_OS::sleep (time)) == -1)
+ {
+ if (errno == EINTR)
+ continue;
+ else
+ ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("%p\n"),
+ ACE_TEXT ("sleep")), -1);
+ }
+ return 0;
+}
+// Listing 1
diff --git a/ACE/examples/APG/Signals/SigInfo.cpp b/ACE/examples/APG/Signals/SigInfo.cpp
new file mode 100644
index 00000000000..0a3186e6099
--- /dev/null
+++ b/ACE/examples/APG/Signals/SigInfo.cpp
@@ -0,0 +1,167 @@
+// $Id$
+
+#include "ace/Log_Msg.h"
+#include "ace/Reactor.h"
+#include "ace/Event_Handler.h"
+#include "ace/Signal.h"
+#include "ace/OS_NS_unistd.h"
+#include "ace/OS_NS_string.h"
+
+#if !defined (ACE_LACKS_UNIX_SIGNALS)
+
+// Listing 1 code/ch11
+class MySignalHandler : public ACE_Event_Handler
+{
+public:
+ MySignalHandler () : ACE_Event_Handler()
+ { }
+
+ // Listing A code/ch11
+ int handle_signal (int signum,
+ siginfo_t * siginfo = 0,
+ ucontext_t * = 0)
+ {
+ ACE_DEBUG ((LM_INFO, ACE_TEXT ("Received signal [%S]\n"),
+ signum));
+ if (siginfo == 0)
+ {
+ ACE_DEBUG ((LM_INFO,
+ ACE_TEXT ("No siginfo_t available for ")
+ ACE_TEXT ("signal [%S]\n"),
+ signum));
+ return 0;
+ }
+ // Listing A
+#if defined (__linux__)
+ // Listing B code/ch11
+ ACE_DEBUG ((LM_INFO,
+ ACE_TEXT ("errno for this signal is %d [%s]\n"),
+ siginfo->si_errno,
+ ACE_OS::strerror (siginfo->si_errno)));
+ ACE_DEBUG ((LM_INFO,
+ ACE_TEXT ("signal was sent by process %d")
+ ACE_TEXT (" / user %d\n"),
+ siginfo->si_pid,
+ siginfo->si_uid));
+
+ switch (siginfo->si_code)
+ {
+ case SI_TIMER:
+ ACE_DEBUG ((LM_INFO, ACE_TEXT ("Timer expiration\n")));
+ break;
+
+ case SI_USER:
+ ACE_DEBUG ((LM_INFO,
+ ACE_TEXT ("Sent by kill, sigsend or raise\n")));
+ break;
+
+ case SI_KERNEL:
+ ACE_DEBUG ((LM_INFO,
+ ACE_TEXT ("Sent by kernel\n")));
+ break;
+ // ...
+ };
+
+ // Listing B
+
+ // Listing C code/ch11
+ switch (signum)
+ {
+ case SIGFPE:
+ switch (siginfo->si_code)
+ {
+ case FPE_INTDIV:
+ case FPE_FLTDIV:
+ ACE_DEBUG ((LM_INFO,
+ ACE_TEXT ("Divide by zero at %@\n"),
+ siginfo->si_addr));
+ break;
+
+ case FPE_INTOVF:
+ case FPE_FLTOVF:
+ ACE_DEBUG ((LM_INFO,
+ ACE_TEXT ("Numeric overflow at %@\n"),
+ siginfo->si_addr));
+ break;
+
+ // ...
+ }
+ break;
+
+ // Listing C
+ // Listing D code/ch11
+ case SIGSEGV:
+ switch (siginfo->si_code)
+ {
+ // ...
+ };
+ break;
+ // Listing D
+
+ // Listing E code/ch11
+ case SIGCHLD:
+ ACE_DEBUG ((LM_INFO,
+ ACE_TEXT ("A child process has exited\n")));
+ ACE_DEBUG ((LM_INFO,
+ ACE_TEXT ("The child consumed %l/%l time\n"),
+ siginfo->si_utime,
+ siginfo->si_stime));
+ ACE_DEBUG ((LM_INFO,
+ ACE_TEXT ("and exited with value %d\n"),
+ siginfo->si_status));
+ break;
+ // ...
+ }
+ // Listing E
+#endif /* __linux__ */
+ return 0;
+ }
+};
+// Listing 1
+
+#endif /* ACE_LACKS_UNIX_SIGNALS */
+
+#if !defined (ACE_LACKS_UNIX_SIGNALS)
+
+int ACE_TMAIN (int, ACE_TCHAR *[])
+{
+#if defined (ACE_LACKS_FORK)
+ ACE_DEBUG ((LM_DEBUG,
+ "This example requires fork()\n"));
+#else
+ // Create a child process so that we can test our
+ // ability to handle SIGCHLD
+
+ // Listing 2 code/ch11
+ ACE_Sig_Set signalSet;
+ signalSet.fill_set ();
+
+ MySignalHandler h1;
+ ACE_Reactor::instance ()->register_handler (signalSet, &h1);
+ pid_t childPid = ACE_OS::fork ();
+ if (childPid == 0) // This is the parent process.
+ {
+ // Exclude B
+ ACE_OS::sleep (10);
+ return 100;
+ // Exclude B
+ }
+ ACE_Reactor::instance ()->run_reactor_event_loop ();
+ // Listing 2
+
+#endif /* ACE_LACKS_FORK */
+
+ return 0;
+}
+
+#else
+
+int
+ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ ACE_DEBUG ((LM_DEBUG,
+ "This example does not work on this platform.\n"));
+ return 1;
+}
+
+#endif /* !ACE_LACKS_UNIX_SIGNALS */
diff --git a/ACE/examples/APG/Signals/signals.mpc b/ACE/examples/APG/Signals/signals.mpc
new file mode 100644
index 00000000000..51947c7a06b
--- /dev/null
+++ b/ACE/examples/APG/Signals/signals.mpc
@@ -0,0 +1,37 @@
+// -*- MPC -*-
+// $Id$
+
+project(SigAction) : aceexe {
+ exename = SigAction
+ Source_Files {
+ SigAction.cpp
+ }
+}
+
+project(SigGuard) : aceexe {
+ exename = SigGuard
+ Source_Files {
+ SigGuard.cpp
+ }
+}
+
+project(SigHandler) : aceexe {
+ exename = SigHandler
+ Source_Files {
+ SigHandler.cpp
+ }
+}
+
+project(SigHandlers) : aceexe {
+ exename = SigHandlers
+ Source_Files {
+ SigHandlers.cpp
+ }
+}
+
+project(SigInfo) : aceexe {
+ exename = SigInfo
+ Source_Files {
+ SigInfo.cpp
+ }
+}
diff --git a/ACE/examples/APG/Sockets/.cvsignore b/ACE/examples/APG/Sockets/.cvsignore
new file mode 100644
index 00000000000..0b2c9d92db4
--- /dev/null
+++ b/ACE/examples/APG/Sockets/.cvsignore
@@ -0,0 +1,8 @@
+Basic
+Basic
+Basic_Robust
+Basic_Robust
+Iovec
+Iovec
+Server
+Server
diff --git a/ACE/examples/APG/Sockets/Basic.cpp b/ACE/examples/APG/Sockets/Basic.cpp
new file mode 100644
index 00000000000..6a20e435b3c
--- /dev/null
+++ b/ACE/examples/APG/Sockets/Basic.cpp
@@ -0,0 +1,35 @@
+// $Id$
+
+#include "ace/INET_Addr.h"
+#include "ace/SOCK_Stream.h"
+#include "ace/SOCK_Connector.h"
+#include "ace/Log_Msg.h"
+
+int ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ // Listing 1 code/ch06
+ ACE_INET_Addr srvr (50000, ACE_LOCALHOST);
+ // Listing 1
+
+ // Listing 2 code/ch06
+ ACE_SOCK_Connector connector;
+ ACE_SOCK_Stream peer;
+
+ if (-1 == connector.connect (peer, srvr))
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("connect")), 1);
+ // Listing 2
+
+ ssize_t bc;
+ char buf[64];
+
+ // Listing 3 code/ch06
+ peer.send_n ("uptime\n", 7);
+ bc = peer.recv (buf, sizeof(buf));
+ write (1, buf, bc);
+ peer.close ();
+ // Listing 3
+
+ return (0);
+}
diff --git a/ACE/examples/APG/Sockets/Basic_Robust.cpp b/ACE/examples/APG/Sockets/Basic_Robust.cpp
new file mode 100644
index 00000000000..361519a4486
--- /dev/null
+++ b/ACE/examples/APG/Sockets/Basic_Robust.cpp
@@ -0,0 +1,137 @@
+// $Id$
+
+#include "ace/OS_NS_errno.h"
+#include "ace/INET_Addr.h"
+#include "ace/SOCK_Stream.h"
+#include "ace/SOCK_Connector.h"
+#include "ace/Log_Msg.h"
+#include "ace/Time_Value.h"
+
+int ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ /*
+ * Here we will use the default ctor and the set()
+ * method to configure it. After each set() we will
+ * display the address as a string and then connect
+ * to each respective server. We can reuse the addr
+ * instance once connection has been established.
+ *
+ // Listing 1 code/ch06
+ ACE_INET_Addr addr;
+ ...
+ addr.set ("HAStatus", ACE_LOCALHOST);
+ ...
+ addr.set ("HALog", ACE_LOCALHOST);
+ // Listing 1
+ *
+ */
+
+ ACE_INET_Addr addr;
+ ACE_TCHAR peerAddress[64];
+
+ // Listing 2 code/ch06
+ addr.set (ACE_TEXT("HAStatus"), ACE_LOCALHOST);
+ if (addr.addr_to_string (peerAddress,
+ sizeof(peerAddress), 0) == 0)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("(%P|%t) Connecting to %s\n"),
+ peerAddress));
+ }
+ // Listing 2
+
+ // Listing 3 code/ch06
+ ACE_SOCK_Stream status;
+ ACE_OS::last_error(0);
+ ACE_SOCK_Connector statusConnector (status, addr);
+ if (ACE_OS::last_error())
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("status")), 100);
+ // Listing 3
+
+ addr.set (ACE_TEXT("HALog"), ACE_LOCALHOST);
+ if (addr.addr_to_string (peerAddress,
+ sizeof(peerAddress), 0) == 0)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("(%P|%t) Connecting to %s\n"),
+ peerAddress ));
+ }
+
+ // Listing 4 code/ch06
+ ACE_SOCK_Connector logConnector;
+ ACE_Time_Value timeout (10);
+ ACE_SOCK_Stream log;
+ if (logConnector.connect (log, addr, &timeout) == -1)
+ {
+ if (ACE_OS::last_error() == ETIME)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("(%P|%t) Timeout while ")
+ ACE_TEXT ("connecting to log server\n")));
+ }
+ else
+ {
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("log")));
+ }
+ return (101);
+ }
+ // Listing 4
+
+ /*
+ * We generally let the OS pick our local port number but
+ * if you want, you can choose that also:
+ // Listing 5 code/ch06
+ ACE_SOCK_Connector logConnector;
+ ACE_INET_Addr local (4200, ACE_LOCALHOST);
+ if (logConnector.connect (log, addr, 0, local) == -1)
+ {
+ ...
+ // Listing 5
+ }
+ */
+
+ char buf[64];
+
+ // Listing 6 code/ch06
+ ACE_Time_Value sendTimeout (0, 5);
+ if (status.send_n ("uptime\n", 7, &sendTimeout) == -1)
+ {
+ if (ACE_OS::last_error() == ETIME)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("(%P|%t) Timeout while sending ")
+ ACE_TEXT ("query to status server\n")));
+ }
+ // Listing 6
+ else
+ {
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("send_n")));
+ }
+ return (102);
+ }
+
+ // Listing 7 code/ch06
+ ssize_t bc ;
+ ACE_Time_Value recvTimeout (0, 1);
+ if ((bc = status.recv (buf, sizeof(buf), &recvTimeout)) == -1)
+ {
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("recv")));
+ return (103);
+ }
+
+ log.send_n (buf, bc);
+ // Listing 7
+
+ status.close ();
+ log.close ();
+
+ return (0);
+}
diff --git a/ACE/examples/APG/Sockets/Iovec.cpp b/ACE/examples/APG/Sockets/Iovec.cpp
new file mode 100644
index 00000000000..fb27b6d562e
--- /dev/null
+++ b/ACE/examples/APG/Sockets/Iovec.cpp
@@ -0,0 +1,84 @@
+// $Id$
+
+#include "ace/INET_Addr.h"
+#include "ace/SOCK_Stream.h"
+#include "ace/SOCK_Connector.h"
+#include "ace/Log_Msg.h"
+
+const char *UPTIME = "uptime";
+const char *HUMIDITY = "humidity";
+const char *TEMPERATURE = "temperature";
+
+void addCommand (iovec [], const char *)
+{}
+
+int ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ ACE_INET_Addr srvr (50000, ACE_LOCALHOST);
+ ACE_SOCK_Connector connector;
+ ACE_SOCK_Stream peer;
+
+ ACE_ASSERT (connector.connect (peer, srvr) != -1);
+
+ ssize_t bc;
+
+ // Listing 1 code/ch06
+ iovec send[4];
+ send[0].iov_base = const_cast<char *> ("up");
+ send[0].iov_len = 2;
+ send[1].iov_base = const_cast<char *> ("time");
+ send[1].iov_len = 4;
+ send[2].iov_base = const_cast<char *> ("\n");
+ send[2].iov_len = 1;
+
+ peer.sendv (send, 3);
+ // Listing 1
+
+ //
+ // A more clever approach would use something like this:
+ // Where the addCommand() method allocates and populates
+ // the query array from a set of global commands.
+ //
+ // Listing 2 code/ch06
+ iovec query[3];
+ addCommand (query, UPTIME);
+ addCommand (query, HUMIDITY);
+ addCommand (query, TEMPERATURE);
+ peer.sendv (query, 3);
+ // Listing 2
+
+ // Listing 3 code/ch06
+ iovec receive[2];
+ receive[0].iov_base = new char [32];
+ receive[0].iov_len = 32;
+ receive[1].iov_base = new char [64];
+ receive[1].iov_len = 64;
+
+ bc = peer.recvv (receive, 2);
+ // Listing 3
+
+ // Listing 4 code/ch06
+ for (int i = 0; i < 2 && bc > 0; ++i)
+ {
+ size_t wc = receive[i].iov_len;
+ if (static_cast<size_t> (bc) < wc)
+ wc = static_cast<size_t> (bc);
+ write (1, receive[i].iov_base, wc);
+ bc -= receive[i].iov_len;
+ delete []
+ (reinterpret_cast<char *> (receive[i].iov_base));
+ }
+ // Listing 4
+
+ // Listing 5 code/ch06
+ peer.send_n ("uptime\n", 7);
+ iovec response;
+ peer.recvv (&response);
+ write (1, response.iov_base, response.iov_len);
+ delete [] reinterpret_cast<char *> (response.iov_base);
+ // Listing 5
+
+ peer.close ();
+
+ return (0);
+}
diff --git a/ACE/examples/APG/Sockets/Makefile.am b/ACE/examples/APG/Sockets/Makefile.am
new file mode 100644
index 00000000000..3409703f567
--- /dev/null
+++ b/ACE/examples/APG/Sockets/Makefile.am
@@ -0,0 +1,72 @@
+## Process this file with automake to create Makefile.in
+##
+## $Id$
+##
+## This file was generated by MPC. Any changes made directly to
+## this file will be lost the next time it is generated.
+##
+## MPC Command:
+## /acebuilds/ACE_wrappers-repository/bin/mwc.pl -include /acebuilds/MPC/config -include /acebuilds/MPC/templates -feature_file /acebuilds/ACE_wrappers-repository/local.features -noreldefs -type automake -exclude build,Kokyu
+
+ACE_BUILDDIR = $(top_builddir)
+ACE_ROOT = $(top_srcdir)
+
+## Makefile.Sockets_Basic.am
+noinst_PROGRAMS = Basic
+
+Basic_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+Basic_SOURCES = \
+ Basic.cpp
+
+Basic_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Makefile.Sockets_Basic_Robust.am
+noinst_PROGRAMS += Basic_Robust
+
+Basic_Robust_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+Basic_Robust_SOURCES = \
+ Basic_Robust.cpp
+
+Basic_Robust_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Makefile.Sockets_Iovec.am
+noinst_PROGRAMS += Iovec
+
+Iovec_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+Iovec_SOURCES = \
+ Iovec.cpp
+
+Iovec_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Makefile.Sockets_Server.am
+noinst_PROGRAMS += Server
+
+Server_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+Server_SOURCES = \
+ Server.cpp
+
+Server_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Clean up template repositories, etc.
+clean-local:
+ -rm -f *~ *.bak *.rpo *.sym lib*.*_pure_* core core.*
+ -rm -f gcctemp.c gcctemp so_locations *.ics
+ -rm -rf cxx_repository ptrepository ti_files
+ -rm -rf templateregistry ir.out
+ -rm -rf ptrepository SunWS_cache Templates.DB
diff --git a/ACE/examples/APG/Sockets/Server.cpp b/ACE/examples/APG/Sockets/Server.cpp
new file mode 100644
index 00000000000..2a9ca7f4f7b
--- /dev/null
+++ b/ACE/examples/APG/Sockets/Server.cpp
@@ -0,0 +1,95 @@
+// $Id$
+
+#include "ace/os_include/os_netdb.h"
+#include "ace/OS_NS_errno.h"
+#include "ace/INET_Addr.h"
+#include "ace/SOCK_Stream.h"
+#include "ace/SOCK_Acceptor.h"
+#include "ace/Log_Msg.h"
+#include "ace/Time_Value.h"
+
+int ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ // Listing 1 code/ch06
+ ACE_INET_Addr port_to_listen ("HAStatus");
+ ACE_SOCK_Acceptor acceptor;
+
+ if (acceptor.open (port_to_listen, 1) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("acceptor.open")),
+ 100);
+ // Listing 1
+
+ /*
+ * The complete open signature:
+ *
+ // Listing 2 code/ch06
+ int open (const ACE_Addr &local_sap,
+ int reuse_addr = 0,
+ int protocol_family = PF_INET,
+ int backlog = ACE_DEFAULT_BACKLOG,
+ int protocol = 0);
+ // Listing 2
+ *
+ */
+
+ while (1)
+ {
+ ACE_SOCK_Stream peer;
+ ACE_INET_Addr peer_addr;
+ ACE_Time_Value timeout (10, 0);
+
+ /*
+ * Basic acceptor usage
+ */
+#if 0
+ // Listing 3 code/ch06
+ if (acceptor.accept (peer) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("(%P|%t) Failed to accept ")
+ ACE_TEXT ("client connection\n")),
+ 100);
+ // Listing 3
+#endif /* 0 */
+
+ // Listing 4 code/ch06
+ if (acceptor.accept (peer, &peer_addr, &timeout, 0) == -1)
+ {
+ if (ACE_OS::last_error() == EINTR)
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("(%P|%t) Interrupted while ")
+ ACE_TEXT ("waiting for connection\n")));
+ else
+ if (ACE_OS::last_error() == ETIMEDOUT)
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("(%P|%t) Timeout while ")
+ ACE_TEXT ("waiting for connection\n")));
+ }
+ // Listing 4
+ // Listing 5 code/ch06
+ else
+ {
+ ACE_TCHAR peer_name[MAXHOSTNAMELEN];
+ peer_addr.addr_to_string (peer_name, MAXHOSTNAMELEN);
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("(%P|%t) Connection from %s\n"),
+ peer_name));
+ // Listing 5
+ // Listing 7 code/ch06
+ char buffer[4096];
+ ssize_t bytes_received;
+
+ while ((bytes_received =
+ peer.recv (buffer, sizeof(buffer))) != -1)
+ {
+ peer.send_n (buffer, bytes_received);
+ }
+
+ peer.close ();
+ // Listing 7
+ }
+ }
+
+ ACE_NOTREACHED (return 0);
+}
diff --git a/ACE/examples/APG/Sockets/sockets.mpc b/ACE/examples/APG/Sockets/sockets.mpc
new file mode 100644
index 00000000000..86064233ac3
--- /dev/null
+++ b/ACE/examples/APG/Sockets/sockets.mpc
@@ -0,0 +1,30 @@
+// -*- MPC -*-
+// $Id$
+
+project(*Basic) : aceexe {
+ exename = Basic
+ Source_Files {
+ Basic.cpp
+ }
+}
+
+project(*Basic Robust) : aceexe {
+ exename = Basic_Robust
+ Source_Files {
+ Basic_Robust.cpp
+ }
+}
+
+project(*Iovec) : aceexe {
+ exename = Iovec
+ Source_Files {
+ Iovec.cpp
+ }
+}
+
+project(*Server) : aceexe {
+ exename = Server
+ Source_Files {
+ Server.cpp
+ }
+}
diff --git a/ACE/examples/APG/Streams/.cvsignore b/ACE/examples/APG/Streams/.cvsignore
new file mode 100644
index 00000000000..ff318c0de98
--- /dev/null
+++ b/ACE/examples/APG/Streams/.cvsignore
@@ -0,0 +1,2 @@
+Answerer
+Answerer
diff --git a/ACE/examples/APG/Streams/Answerer.cpp b/ACE/examples/APG/Streams/Answerer.cpp
new file mode 100644
index 00000000000..507b6172108
--- /dev/null
+++ b/ACE/examples/APG/Streams/Answerer.cpp
@@ -0,0 +1,403 @@
+/**
+ * $Id$
+ *
+ * Streams Listing 01
+ *
+ * An answering machine based on a one-way ACE_Stream
+ */
+
+#include "ace/OS_NS_string.h"
+#include "ace/Stream.h"
+#include "ace/Message_Block.h"
+#include "ace/FILE_IO.h"
+
+#include "MessageInfo.h"
+#include "Message.h"
+#include "BasicTask.h"
+#include "EndTask.h"
+#include "Util.h"
+#include "RecordingDevice.h"
+
+// Listing 21 code/ch18
+class AnswerIncomingCall : public BasicTask
+{
+protected:
+ virtual int process (Message *message)
+ {
+ ACE_TRACE (ACE_TEXT ("AnswerIncomingCall::process()"));
+
+ if (message->recorder ()->answer_call () < 0)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("AnswerIncomingCall")),
+ -1);
+ return 0;
+ }
+};
+// Listing 21
+
+// Listing 22 code/ch18
+class GetCallerId : public BasicTask
+{
+protected:
+ virtual int process (Message *message)
+ {
+ ACE_TRACE (ACE_TEXT ("GetCallerId::process()"));
+
+ CallerId *id;
+ id = message->recorder ()->retrieve_callerId ();
+ if (!id)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("GetCallerId")),
+ -1);
+
+ message->caller_id (id);
+ return 0;
+ }
+};
+// Listing 22
+
+// Listing 23 code/ch18
+class PlayOutgoingMessage : public BasicTask
+{
+protected:
+ virtual int process (Message *message)
+ {
+ ACE_TRACE (ACE_TEXT ("PlayOutgoingMessage::process()"));
+
+ ACE_FILE_Addr outgoing_message =
+ this->get_outgoing_message (message);
+
+ int pmrv =
+ message->recorder ()->play_message (outgoing_message);
+ if (pmrv < 0)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("PlayOutgoingMessage")),
+ -1);
+ return 0;
+ }
+
+ ACE_FILE_Addr get_outgoing_message (Message *)
+ {
+ // Exclude 23
+ return ACE_FILE_Addr (ACE_TEXT ("/tmp/outgoing_message"));
+ // Exclude 23
+ }
+};
+// Listing 23
+
+// Listing 24 code/ch18
+class RecordIncomingMessage : public BasicTask
+{
+protected:
+ virtual int process (Message *message)
+ {
+ ACE_TRACE (ACE_TEXT ("RecordIncomingMessage::process()"));
+
+ ACE_FILE_Addr incoming_message =
+ this->get_incoming_message_queue ();
+
+ MessageType *type =
+ message->recorder ()->record_message (incoming_message);
+ if (!type)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("RecordIncomingMessage")),
+ -1);
+ message->incoming_message (incoming_message, type);
+ return 0;
+ }
+
+ ACE_FILE_Addr get_incoming_message_queue (void)
+ {
+ // Exclude 24
+ return ACE_FILE_Addr (ACE_TEXT ("/tmp/incoming_message"));
+ // Exclude 24
+ }
+};
+// Listing 24
+
+// Listing 25 code/ch18
+class ReleaseDevice : public BasicTask
+{
+protected:
+ virtual int process (Message *message)
+ {
+ ACE_TRACE (ACE_TEXT ("ReleaseDevice::process()"));
+ message->recorder ()->release ();
+ return 0;
+ }
+};
+// Listing 25
+
+// Listing 26 code/ch18
+class EncodeMessage : public BasicTask
+{
+protected:
+ virtual int process (Message *message)
+ {
+ ACE_TRACE (ACE_TEXT ("ReleaseDevice::process()"));
+
+ ACE_FILE_Addr &incoming = message->addr ();
+ ACE_FILE_Addr addr = this->get_message_destination (message);
+
+ if (message->is_text ())
+ Util::convert_to_unicode (incoming, addr);
+ else if (message->is_audio ())
+ Util::convert_to_mp3 (incoming, addr);
+ else if (message->is_video ())
+ Util::convert_to_mpeg (incoming, addr);
+
+ message->addr (addr);
+ return 0;
+ }
+
+ ACE_FILE_Addr get_message_destination (Message *)
+ {
+ // Exclude 26
+ return ACE_FILE_Addr (ACE_TEXT ("/tmp/encoded_message"));
+ // Exclude 26
+ }
+};
+// Listing 26
+
+// Listing 27 code/ch18
+class SaveMetaData : public BasicTask
+{
+protected:
+ virtual int process (Message *message)
+ {
+ ACE_TRACE (ACE_TEXT ("SaveMetaData::process()"));
+
+ ACE_TString path (message->addr ().get_path_name ());
+ path += ACE_TEXT (".xml");
+
+ ACE_FILE_Connector connector;
+ ACE_FILE_IO file;
+ ACE_FILE_Addr addr (path.c_str ());
+ if (connector.connect (file, addr) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("create meta-data file")),
+ 0);
+
+ file.truncate (0);
+ this->write (file, "<Message>\n");
+ // ...
+ this->write (file, "</Message>\n");
+ file.close ();
+ return 0;
+ }
+
+private:
+ int write (ACE_FILE_IO &file, const char *str)
+ {
+ return file.send (str, ACE_OS::strlen (str));
+ }
+};
+// Listing 27
+
+// Listing 28 code/ch18
+class NotifySomeone : public BasicTask
+{
+protected:
+ virtual int process (Message *message)
+ {
+ ACE_TRACE (ACE_TEXT ("NotifySomeone::process()"));
+
+ // Format an email to tell someone about the
+ // newly received message.
+ // ...
+
+ // Display message information in the logfile
+ ACE_DEBUG ((LM_INFO,
+ ACE_TEXT ("New message from %s ")
+ ACE_TEXT ("received and stored at %s\n"),
+ message->caller_id ()->string (),
+ message->addr ().get_path_name ()));
+ return 0;
+ }
+};
+// Listing 28
+
+// Listing 10 code/ch18
+class RecordingStream : public ACE_Stream<ACE_MT_SYNCH>
+{
+public:
+ typedef ACE_Stream<ACE_MT_SYNCH> inherited;
+ typedef ACE_Module<ACE_MT_SYNCH> Module;
+
+ RecordingStream () : inherited()
+ { }
+// Listing 10
+
+ // Listing 1000 code/ch18
+ virtual int open (void *arg,
+ Module *head = 0, Module *tail = 0)
+ {
+ if (tail == 0)
+ ACE_NEW_RETURN (tail,
+ Module (ACE_TEXT ("End Module"), new EndTask ()),
+ -1);
+ this->inherited::open (arg, head, tail);
+ // Listing 1000
+
+ // Listing 1001 code/ch18
+ Module *answerIncomingCallModule;
+ ACE_NEW_RETURN (answerIncomingCallModule,
+ Module (ACE_TEXT ("Answer Incoming Call"),
+ new AnswerIncomingCall ()),
+ -1);
+
+ // Listing 11 code/ch18
+ Module *getCallerIdModule;
+ ACE_NEW_RETURN (getCallerIdModule,
+ Module (ACE_TEXT ("Get Caller ID"), new GetCallerId ()),
+ -1);
+ // Listing 11
+
+ Module *playOGMModule;
+ ACE_NEW_RETURN (playOGMModule,
+ Module (ACE_TEXT ("Play Outgoing Message"),
+ new PlayOutgoingMessage ()),
+ -1);
+
+ Module *recordModule;
+ ACE_NEW_RETURN (recordModule,
+ Module (ACE_TEXT ("Record Incoming Message"),
+ new RecordIncomingMessage ()),
+ -1);
+
+ Module *releaseModule;
+ ACE_NEW_RETURN (releaseModule,
+ Module (ACE_TEXT ("Release Device"),
+ new ReleaseDevice ()),
+ -1);
+
+ Module *conversionModule;
+ ACE_NEW_RETURN (conversionModule,
+ Module (ACE_TEXT ("Encode Message"),
+ new EncodeMessage ()),
+ -1);
+
+ Module *saveMetaDataModule;
+ ACE_NEW_RETURN (saveMetaDataModule,
+ Module (ACE_TEXT ("Save Meta-Data"),
+ new SaveMetaData ()),
+ -1);
+
+ Module *notificationModule;
+ ACE_NEW_RETURN (notificationModule,
+ Module (ACE_TEXT ("Notify Someone"),
+ new NotifySomeone ()),
+ -1);
+ // Listing 1001
+
+ // Listing 12 code/ch18
+ if (this->push (notificationModule) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("Failed to push %p\n"),
+ ACE_TEXT ("notificationModule")),
+ -1);
+ if (this->push (saveMetaDataModule) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("Failed to push %p\n"),
+ ACE_TEXT ("saveMetaDataModule")),
+ -1);
+ if (this->push (conversionModule) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("Failed to push %p\n"),
+ ACE_TEXT ("conversionModule")),
+ -1);
+ if (this->push (releaseModule) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("Failed to push %p\n"),
+ ACE_TEXT ("releaseModule")),
+ -1);
+ if (this->push (recordModule) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("Failed to push %p\n"),
+ ACE_TEXT ("recordModule")),
+ -1);
+ if (this->push (playOGMModule) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("Failed to push %p\n"),
+ ACE_TEXT ("playOGMModule")),
+ -1);
+ if (this->push (getCallerIdModule) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("Failed to push %p\n"),
+ ACE_TEXT ("getCallerIdModule")),
+ -1);
+ if (this->push (answerIncomingCallModule) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("Failed to push %p\n")
+ ACE_TEXT ("answerIncomingCallModule")),
+ -1);
+ // Listing 12
+
+ return 0;
+ }
+
+ // Listing 13 code/ch18
+ int record (RecordingDevice *recorder)
+ {
+ ACE_Message_Block * mb;
+ ACE_NEW_RETURN (mb, ACE_Message_Block (sizeof(Message)), -1);
+
+ Message *message = (Message *)mb->wr_ptr ();
+ mb->wr_ptr (sizeof(Message));
+
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("RecordingStream::record() - ")
+ ACE_TEXT ("message->recorder(recorder)\n")));
+ message->recorder (recorder);
+
+ int rval = this->put (mb);
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("RecordingStream::record() - ")
+ ACE_TEXT ("this->put() returns %d\n"),
+ rval));
+ return rval;
+ }
+ // Listing 13
+};
+
+
+// Listing 1 code/ch18
+int ACE_TMAIN (int argc, ACE_TCHAR *argv[])
+{
+ RecordingDevice *recorder =
+ RecordingDeviceFactory::instantiate (argc, argv);
+ // Listing 1
+
+ // Listing 2 code/ch18
+ RecordingStream *recording_stream;
+ ACE_NEW_RETURN (recording_stream, RecordingStream, -1);
+
+ if (recording_stream->open (0) < 0)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("RecordingStream->open()")),
+ 0);
+ // Listing 2
+
+ // Listing 3 code/ch18
+ for (;;)
+ {
+ ACE_DEBUG ((LM_INFO,
+ ACE_TEXT ("Waiting for incoming message\n")));
+ RecordingDevice *activeRecorder =
+ recorder->wait_for_activity ();
+
+ ACE_DEBUG ((LM_INFO,
+ ACE_TEXT ("Initiating recording process\n")));
+
+ recording_stream->record (activeRecorder);
+ }
+ // Listing 3
+
+ return 0;
+}
diff --git a/ACE/examples/APG/Streams/BasicTask.h b/ACE/examples/APG/Streams/BasicTask.h
new file mode 100644
index 00000000000..edebc397998
--- /dev/null
+++ b/ACE/examples/APG/Streams/BasicTask.h
@@ -0,0 +1,143 @@
+/* -*- C++ -*- */
+// $Id$
+
+#ifndef BASIC_TASK_H
+#define BASIC_TASK_H
+
+#include "ace/Task_T.h"
+#include "ace/ace_wchar.h"
+
+// Listing 100 code/ch18
+class BasicTask : public ACE_Task<ACE_MT_SYNCH>
+{
+public:
+ typedef ACE_Task<ACE_MT_SYNCH> inherited;
+
+ BasicTask () : inherited()
+ { }
+
+ virtual int open (void * = 0)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("BasicTask::open() starting ")
+ ACE_TEXT ("%d threads\n"),
+ this->desired_threads ()));
+
+ return this->activate (THR_NEW_LWP | THR_JOINABLE,
+ this->desired_threads ());
+ }
+ // Listing 100
+
+ // Listing 101 code/ch18
+ int put (ACE_Message_Block *message,
+ ACE_Time_Value *timeout)
+ {
+ return this->putq (message, timeout);
+ }
+ // Listing 101
+
+ // Listing 1020 code/ch18
+ virtual int svc (void)
+ {
+ for (ACE_Message_Block *message = 0; ; )
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("BasicTask::svc() - ")
+ ACE_TEXT ("waiting for work\n" )));
+
+ if (this->getq (message) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("%p\n"),
+ ACE_TEXT ("getq")),
+ -1);
+ // Listing 1020
+
+ // Listing 1021 code/ch18
+ if (message->msg_type () == ACE_Message_Block::MB_HANGUP)
+ {
+ if (this->putq (message) == -1)
+ {
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("Task::svc() putq")));
+ message->release ();
+ }
+ break;
+ }
+ // Listing 1021
+
+ // Listing 1022 code/ch18
+ Message *recordedMessage =
+ (Message *)message->rd_ptr ();
+
+ if (this->process (recordedMessage) == -1)
+ {
+ message->release ();
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("process")),
+ -1);
+ }
+ // Listing 1022
+
+ // Listing 1023 code/ch18
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("BasicTask::svc() - ")
+ ACE_TEXT ("Continue to next stage\n" )));
+ if (this->next_step (message) < 0)
+ {
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("put_next failed")));
+ message->release ();
+ break;
+ }
+ // Listing 1023
+ }
+
+ return 0;
+ }
+
+ // Listing 103 code/ch18
+ virtual int close (u_long flags)
+ {
+ int rval = 0;
+
+ if (flags == 1)
+ {
+ ACE_Message_Block *hangup = new ACE_Message_Block ();
+ hangup->msg_type (ACE_Message_Block::MB_HANGUP);
+ if (this->putq (hangup) == -1)
+ {
+ hangup->release ();
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("Task::close() putq")),
+ -1);
+ }
+
+ rval = this->wait ();
+ }
+
+ return rval;
+ }
+ // Listing 103
+
+ // Listing 105 code/ch18
+protected:
+ virtual int next_step (ACE_Message_Block *message_block)
+ {
+ return this->put_next (message_block);
+ }
+ // Listing 105
+
+ // Listing 104 code/ch18
+ virtual int process (Message *message) = 0;
+
+ virtual int desired_threads (void)
+ {
+ return 1;
+ }
+};
+// Listing 104
+
+#endif /* BASIC_TASK_H */
diff --git a/ACE/examples/APG/Streams/Command.h b/ACE/examples/APG/Streams/Command.h
new file mode 100644
index 00000000000..eae0f5ecb5f
--- /dev/null
+++ b/ACE/examples/APG/Streams/Command.h
@@ -0,0 +1,40 @@
+/* -*- C++ -*- */
+// $Id$
+
+#ifndef COMMAND_H
+#define COMMAND_H
+
+#include "ace/SString.h"
+#include "ace/Message_Block.h"
+
+// Listing 01 code/ch18
+class Command : public ACE_Data_Block
+{
+public:
+ // Result Values
+ enum {
+ RESULT_PASS = 1,
+ RESULT_SUCCESS = 0,
+ RESULT_FAILURE = -1
+ };
+
+ // Commands
+ enum {
+ CMD_UNKNOWN = -1,
+ CMD_ANSWER_CALL = 10,
+ CMD_RETRIEVE_CALLER_ID,
+ CMD_PLAY_MESSAGE,
+ CMD_RECORD_MESSAGE
+ } commands;
+
+ int flags_;
+ int command_;
+
+ void *extra_data_;
+
+ int numeric_result_;
+ ACE_TString result_;
+};
+// Listing 01
+
+#endif /* COMMAND_H */
diff --git a/ACE/examples/APG/Streams/CommandModule.cpp b/ACE/examples/APG/Streams/CommandModule.cpp
new file mode 100644
index 00000000000..9ee5a92918a
--- /dev/null
+++ b/ACE/examples/APG/Streams/CommandModule.cpp
@@ -0,0 +1,20 @@
+// $Id$
+
+#include "CommandModule.h"
+
+// Listing 01 code/ch18
+CommandModule::CommandModule (const ACE_TCHAR *module_name,
+ CommandTask *writer,
+ CommandTask *reader,
+ ACE_SOCK_Stream *peer)
+ : inherited(module_name, writer, reader, peer)
+{ }
+// Listing 01
+
+// Listing 02 code/ch18
+ACE_SOCK_Stream &CommandModule::peer (void)
+{
+ ACE_SOCK_Stream *peer = (ACE_SOCK_Stream *)this->arg ();
+ return *peer;
+}
+// Listing 02
diff --git a/ACE/examples/APG/Streams/CommandModule.h b/ACE/examples/APG/Streams/CommandModule.h
new file mode 100644
index 00000000000..7fe65b81f78
--- /dev/null
+++ b/ACE/examples/APG/Streams/CommandModule.h
@@ -0,0 +1,27 @@
+/* -*- C++ -*- */
+// $Id$
+
+#ifndef COMMAND_MODULE_H
+#define COMMAND_MODULE_H
+
+#include "ace/Module.h"
+#include "ace/SOCK_Stream.h"
+#include "CommandTask.h"
+
+// Listing 01 code/ch18
+class CommandModule : public ACE_Module<ACE_MT_SYNCH>
+{
+public:
+ typedef ACE_Module<ACE_MT_SYNCH> inherited;
+ typedef ACE_Task<ACE_MT_SYNCH> Task;
+
+ CommandModule (const ACE_TCHAR *module_name,
+ CommandTask *writer,
+ CommandTask *reader,
+ ACE_SOCK_Stream *peer);
+
+ ACE_SOCK_Stream &peer (void);
+};
+// Listing 01
+
+#endif /* COMMAND_MODULE_H */
diff --git a/ACE/examples/APG/Streams/CommandStream.cpp b/ACE/examples/APG/Streams/CommandStream.cpp
new file mode 100644
index 00000000000..def3f123d77
--- /dev/null
+++ b/ACE/examples/APG/Streams/CommandStream.cpp
@@ -0,0 +1,97 @@
+// $Id$
+
+#include "ace/Log_Msg.h"
+#include "ace/OS_Memory.h"
+#include "CommandStream.h"
+#include "Command.h"
+#include "CommandModule.h"
+#include "CommandTasks.h"
+
+// Gotcha: superclass' open() won't open head/tail modules
+// Gotcha!! Must open the stream before pushing modules!
+
+// Listing 01 code/ch18
+int CommandStream::open (void *arg,
+ ACE_Module<ACE_MT_SYNCH> *head,
+ ACE_Module<ACE_MT_SYNCH> *tail)
+{
+ ACE_TRACE (ACE_TEXT ("CommandStream::open(peer)"));
+
+ if (this->inherited::open (arg, head, tail) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("%p\n"),
+ ACE_TEXT ("Failed to open superclass")),
+ -1);
+ // Listing 01
+
+ // Listing 02 code/ch18
+ CommandModule *answerCallModule;
+ ACE_NEW_RETURN (answerCallModule,
+ AnswerCallModule (this->peer_),
+ -1);
+
+ CommandModule *retrieveCallerIdModule;
+ ACE_NEW_RETURN (retrieveCallerIdModule,
+ RetrieveCallerIdModule (this->peer_),
+ -1);
+
+ CommandModule *playMessageModule;
+ ACE_NEW_RETURN (playMessageModule,
+ PlayMessageModule (this->peer_),
+ -1);
+
+ CommandModule *recordMessageModule;
+ ACE_NEW_RETURN (recordMessageModule,
+ RecordMessageModule (this->peer_),
+ -1);
+ // Listing 02
+
+ // Listing 03 code/ch18
+ if (this->push (answerCallModule) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("Failed to push %p\n"),
+ answerCallModule->name()),
+ -1);
+
+ if (this->push (retrieveCallerIdModule) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("Failed to push %p\n"),
+ retrieveCallerIdModule->name()),
+ -1);
+
+ if (this->push (playMessageModule) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("Failed to push %p\n"),
+ playMessageModule->name()),
+ -1);
+
+ if (this->push (recordMessageModule) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("Failed to push %p\n"),
+ recordMessageModule->name()),
+ -1);
+ // Listing 03
+ return 0;
+}
+
+// Listing 04 code/ch18
+Command *CommandStream::execute (Command *command)
+{
+ ACE_Message_Block *mb;
+ ACE_NEW_RETURN (mb, ACE_Message_Block (command), 0);
+ if (this->put (mb) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("Fail on put command %d: %p\n"),
+ command->command_,
+ ACE_TEXT ("")),
+ 0);
+
+ this->get (mb);
+ command = (Command *)mb->data_block ();
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("Command (%d) returns (%d)\n"),
+ command->command_,
+ command->numeric_result_));
+
+ return command;
+}
+// Listing 04
diff --git a/ACE/examples/APG/Streams/CommandStream.h b/ACE/examples/APG/Streams/CommandStream.h
new file mode 100644
index 00000000000..97e9e673f7c
--- /dev/null
+++ b/ACE/examples/APG/Streams/CommandStream.h
@@ -0,0 +1,44 @@
+/* -*- C++ -*- */
+// $Id$
+
+#ifndef COMMAND_STREAM_H
+#define COMMAND_STREAM_H
+
+#include "ace/Module.h"
+#include "ace/Stream.h"
+#include "ace/SOCK_Stream.h"
+#include "ace/Synch_Traits.h"
+
+#include "Command.h"
+
+// A CommandStream is a bidirectional ACE_Stream implementing a chain
+// of commands. A message will move down the stream until a
+// CommandModule is capable of processing it. After processing, it
+// will move on down the stream to the end. Data received from the
+// tail will likewise move up the stream until the downstream's
+// partner module is encoutered. The retrieved data will be processed
+// and continue on up the stream.
+
+// Listing 01 code/ch18
+class CommandStream : public ACE_Stream<ACE_MT_SYNCH>
+{
+public:
+ typedef ACE_Stream<ACE_MT_SYNCH> inherited;
+
+ CommandStream (ACE_SOCK_Stream *peer)
+ : inherited (), peer_(peer) { }
+
+ virtual int open (void *arg,
+ ACE_Module<ACE_MT_SYNCH> *head = 0,
+ ACE_Module<ACE_MT_SYNCH> *tail = 0);
+
+ Command *execute (Command *command);
+
+private:
+ CommandStream () { }
+
+ ACE_SOCK_Stream *peer_;
+};
+// Listing 01
+
+#endif /* COMMAND_STREAM_H */
diff --git a/ACE/examples/APG/Streams/CommandTask.cpp b/ACE/examples/APG/Streams/CommandTask.cpp
new file mode 100644
index 00000000000..7ad63166ffd
--- /dev/null
+++ b/ACE/examples/APG/Streams/CommandTask.cpp
@@ -0,0 +1,153 @@
+// $Id$
+
+#include "CommandTask.h"
+
+// Listing 01 code/ch18
+CommandTask::CommandTask (int command)
+ : inherited (), command_(command)
+{ }
+// Listing 01
+
+// Listing 02 code/ch18
+int CommandTask::open (void *)
+{
+ return this->activate ();
+}
+// Listing 02
+
+// Listing 03 code/ch18
+int CommandTask::put (ACE_Message_Block *message,
+ ACE_Time_Value *timeout)
+{
+ return this->putq (message, timeout);
+}
+// Listing 03
+
+// Listing 04 code/ch18
+int CommandTask::process (Command *)
+{
+ ACE_TRACE (ACE_TEXT ("CommandTask::process()"));
+ return Command::RESULT_FAILURE;
+}
+// Listing 04
+
+// Listing 05 code/ch18
+int CommandTask::close (u_long flags)
+{
+ int rval = 0;
+ if (flags == 1)
+ {
+ ACE_Message_Block *hangup = new ACE_Message_Block;
+ hangup->msg_type (ACE_Message_Block::MB_HANGUP);
+ if (this->putq (hangup->duplicate ()) == -1)
+ {
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("Task::close() putq")),
+ -1);
+ }
+
+ hangup->release ();
+ rval = this->wait ();
+ }
+
+ return rval;
+}
+// Listing 05
+
+// Listing 06 code/ch18
+// Listing 061 code/ch18
+int CommandTask::svc (void)
+{
+ ACE_Message_Block *message;
+
+ for (;;)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("CommandTask::svc() - ")
+ ACE_TEXT ("%s waiting for work\n"),
+ this->module ()->name ()));
+
+ if (this->getq (message) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("getq")),
+ -1);
+
+ if (message->msg_type () == ACE_Message_Block::MB_HANGUP)
+ {
+ if (this->putq (message->duplicate ()) == -1)
+ {
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("Task::svc() putq")),
+ -1);
+ }
+
+ message->release ();
+ break;
+ }
+ // Listing 061
+
+ // Listing 062 code/ch18
+ Command *command = (Command *)message->data_block ();
+
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("CommandTask::svc() - ")
+ ACE_TEXT ("%s got work request %d\n"),
+ this->module ()->name (),
+ command->command_));
+
+ if (command->command_ != this->command_)
+ {
+ this->put_next (message->duplicate ());
+ }
+ // Listing 062
+ // Listing 063 code/ch18
+ else
+ {
+ int result = this->process (command);
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("CommandTask::svc() - ")
+ ACE_TEXT ("%s work request %d result is %d\n"),
+ this->module ()->name (),
+ command->command_,
+ result));
+
+ if (result == Command::RESULT_FAILURE)
+ {
+ command->numeric_result_ = -1;
+ }
+ // Listing 063
+ // Listing 064 code/ch18
+ else if (result == Command::RESULT_PASS)
+ {
+ this->put_next (message->duplicate ());
+ }
+ // Listing 064
+ // Listing 065 code/ch18
+ else // result == Command::RESULT_SUCCESS
+ {
+ if (this->is_writer ())
+ {
+ this->sibling ()->putq
+ (message->duplicate ());
+ }
+ // Listing 065
+ // Listing 066 code/ch18
+ else // this->is_reader ()
+ {
+ this->put_next (message->duplicate ());
+ }
+ // Listing 066
+ } // result == ...
+ } // command->command_ ? = this->command_
+
+ // Listing 067 code/ch18
+ message->release ();
+ } // for (;;)
+
+ return 0;
+}
+// Listing 067
+// Listing 06
diff --git a/ACE/examples/APG/Streams/CommandTask.h b/ACE/examples/APG/Streams/CommandTask.h
new file mode 100644
index 00000000000..ae78017b0f9
--- /dev/null
+++ b/ACE/examples/APG/Streams/CommandTask.h
@@ -0,0 +1,39 @@
+/* -*- C++ -*- */
+// $Id$
+
+#ifndef COMMAND_TASK_H
+#define COMMAND_TASK_H
+
+#include "ace/Task.h"
+#include "ace/Module.h"
+
+#include "Command.h"
+
+// Listing 01 code/ch18
+class CommandTask : public ACE_Task<ACE_MT_SYNCH>
+{
+public:
+ typedef ACE_Task<ACE_MT_SYNCH> inherited;
+
+ virtual ~CommandTask () { }
+
+ virtual int open (void * = 0 );
+
+ int put (ACE_Message_Block *message,
+ ACE_Time_Value *timeout);
+
+ virtual int svc (void);
+
+ virtual int close (u_long flags);
+
+protected:
+ CommandTask (int command);
+
+ virtual int process (Command *message);
+
+ int command_;
+};
+// Listing 01
+
+
+#endif /* COMMAND_TASK_H */
diff --git a/ACE/examples/APG/Streams/CommandTasks.cpp b/ACE/examples/APG/Streams/CommandTasks.cpp
new file mode 100644
index 00000000000..78a5e2de451
--- /dev/null
+++ b/ACE/examples/APG/Streams/CommandTasks.cpp
@@ -0,0 +1,221 @@
+// $Id$
+
+#include "ace/FILE_Addr.h"
+#include "ace/FILE_Connector.h"
+#include "ace/FILE_IO.h"
+
+#include "Command.h"
+#include "CommandTasks.h"
+#include "RecordingDevice_Text.h"
+
+// Listing 011 code/ch18
+AnswerCallModule::AnswerCallModule (ACE_SOCK_Stream *peer)
+ : CommandModule (ACE_TEXT ("AnswerCall Module"),
+ new AnswerCallDownstreamTask (),
+ new AnswerCallUpstreamTask (),
+ peer)
+{ }
+// Listing 011
+// Listing 012 code/ch18
+AnswerCallDownstreamTask::AnswerCallDownstreamTask (void)
+ : CommandTask(Command::CMD_ANSWER_CALL)
+{ }
+// Listing 012
+// Listing 013 code/ch18
+int AnswerCallDownstreamTask::process (Command *command)
+{
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Answer Call (downstream)\n")));
+
+ TextListenerAcceptor *acceptor =
+ (TextListenerAcceptor *)command->extra_data_;
+
+ CommandModule *module =
+ (CommandModule*)this->module ();
+
+ command->numeric_result_ =
+ acceptor->accept (module->peer ());
+
+ acceptor->release ();
+ return Command::RESULT_SUCCESS;
+}
+// Listing 013
+// Listing 014 code/ch18
+AnswerCallUpstreamTask::AnswerCallUpstreamTask (void)
+ : CommandTask(Command::CMD_ANSWER_CALL)
+{ }
+// Listing 014
+// Listing 015 code/ch18
+int AnswerCallUpstreamTask::process (Command *)
+{
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Answer Call (upstream)\n")));
+
+ return Command::RESULT_SUCCESS;
+}
+// Listing 015
+
+// Listing 021 code/ch18
+RetrieveCallerIdModule::RetrieveCallerIdModule
+ (ACE_SOCK_Stream *peer)
+ : CommandModule (ACE_TEXT ("RetrieveCallerId Module"),
+ new RetrieveCallerIdDownstreamTask (),
+ new RetrieveCallerIdUpstreamTask (),
+ peer)
+{ }
+// Listing 021
+// Listing 022 code/ch18
+RetrieveCallerIdDownstreamTask::RetrieveCallerIdDownstreamTask
+ (void)
+ : CommandTask(Command::CMD_RETRIEVE_CALLER_ID)
+{ }
+
+int RetrieveCallerIdDownstreamTask::process (Command *)
+{
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("Retrieving Caller ID data\n")));
+
+ return Command::RESULT_SUCCESS;
+}
+// Listing 022
+// Listing 023 code/ch18
+RetrieveCallerIdUpstreamTask::RetrieveCallerIdUpstreamTask
+ (void)
+ : CommandTask(Command::CMD_RETRIEVE_CALLER_ID)
+{ }
+
+int RetrieveCallerIdUpstreamTask::process (Command *command)
+{
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("Returning Caller ID data\n")));
+
+ ACE_INET_Addr remote_addr;
+
+ CommandModule *module =
+ (CommandModule*)this->module ();
+
+ module->peer ().get_remote_addr (remote_addr);
+ ACE_TCHAR remote_addr_str[256];
+ remote_addr.addr_to_string (remote_addr_str, 256);
+ command->result_ = ACE_TString (remote_addr_str);
+
+ return Command::RESULT_SUCCESS;
+}
+// Listing 023
+
+PlayMessageModule::PlayMessageModule (ACE_SOCK_Stream *peer)
+ : CommandModule (ACE_TEXT ("PlayMessage Module"),
+ new PlayMessageDownstreamTask (),
+ new PlayMessageUpstreamTask (),
+ peer)
+{ }
+
+PlayMessageDownstreamTask::PlayMessageDownstreamTask (void)
+ : CommandTask(Command::CMD_PLAY_MESSAGE)
+{ }
+// Listing 032 code/ch18
+int PlayMessageDownstreamTask::process (Command *command)
+{
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("Play Outgoing Message\n")));
+
+ ACE_FILE_Connector connector;
+ ACE_FILE_IO file;
+
+ ACE_FILE_Addr *addr =
+ (ACE_FILE_Addr *)command->extra_data_;
+
+ if (connector.connect (file, *addr) == -1)
+ {
+ command->numeric_result_ = -1;
+ }
+ else
+ {
+ command->numeric_result_ = 0;
+
+ CommandModule *module =
+ (CommandModule*)this->module ();
+
+ char rwbuf[512];
+ ssize_t rwbytes;
+ while ((rwbytes = file.recv (rwbuf, 512)) > 0)
+ {
+ module->peer ().send_n (rwbuf, rwbytes);
+ }
+ }
+
+ return Command::RESULT_SUCCESS;
+}
+// Listing 032
+PlayMessageUpstreamTask::PlayMessageUpstreamTask (void)
+ : CommandTask(Command::CMD_PLAY_MESSAGE)
+{ }
+
+int PlayMessageUpstreamTask::process (Command *command)
+{
+ ACE_FILE_Addr * addr =
+ (ACE_FILE_Addr *)command->extra_data_;
+
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("Outgoing message (%s) sent\n"),
+ addr->get_path_name ()));
+
+ return Command::RESULT_SUCCESS;
+}
+
+RecordMessageModule::RecordMessageModule (ACE_SOCK_Stream *peer)
+ : CommandModule (ACE_TEXT ("RecordMessage Module"),
+ new RecordMessageDownstreamTask (),
+ new RecordMessageUpstreamTask (),
+ peer)
+{ }
+
+RecordMessageDownstreamTask::RecordMessageDownstreamTask (void)
+ : CommandTask(Command::CMD_RECORD_MESSAGE)
+{ }
+
+int RecordMessageDownstreamTask::process (Command *)
+{
+ return Command::RESULT_SUCCESS;
+}
+
+RecordMessageUpstreamTask::RecordMessageUpstreamTask (void)
+ : CommandTask(Command::CMD_RECORD_MESSAGE)
+{ }
+// Listing 033 code/ch18
+int RecordMessageUpstreamTask::process (Command *command)
+{
+ // Collect whatever the peer sends and write into the
+ // specified file.
+ ACE_FILE_Connector connector;
+ ACE_FILE_IO file;
+
+ ACE_FILE_Addr *addr =
+ (ACE_FILE_Addr *)command->extra_data_;
+
+ if (connector.connect (file, *addr) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("create file")),
+ Command::RESULT_FAILURE);
+ file.truncate (0);
+
+ CommandModule *module =
+ (CommandModule*)this->module ();
+
+ ssize_t total_bytes = 0;
+ char rwbuf[512];
+ ssize_t rwbytes;
+ while ((rwbytes = module->peer ().recv (rwbuf, 512)) > 0)
+ {
+ total_bytes += file.send_n (rwbuf, rwbytes);
+ }
+
+ file.close ();
+
+ ACE_DEBUG ((LM_INFO,
+ ACE_TEXT ("RecordMessageUpstreamTask ")
+ ACE_TEXT ("- recorded %d byte message\n"),
+ total_bytes));
+
+ return Command::RESULT_SUCCESS;
+}
+// Listing 033
diff --git a/ACE/examples/APG/Streams/CommandTasks.h b/ACE/examples/APG/Streams/CommandTasks.h
new file mode 100644
index 00000000000..0d55d4da07b
--- /dev/null
+++ b/ACE/examples/APG/Streams/CommandTasks.h
@@ -0,0 +1,108 @@
+/* -*- C++ -*- */
+// $Id$
+
+#ifndef COMMAND_TASKS_H
+#define COMMAND_TASKS_H
+
+#include "ace/SOCK_Stream.h"
+
+#include "Command.h"
+#include "CommandTask.h"
+#include "CommandModule.h"
+
+// CommandModule and CommandTask objects that implement the command
+// stream functions.
+
+// Listing 011 code/ch18
+class AnswerCallModule : public CommandModule
+{
+public:
+ AnswerCallModule (ACE_SOCK_Stream * peer);
+};
+// Listing 011
+// Listing 012 code/ch18
+class AnswerCallDownstreamTask : public CommandTask
+{
+public:
+ AnswerCallDownstreamTask ();
+protected:
+ virtual int process (Command *command);
+};
+// Listing 012
+// Listing 013 code/ch18
+class AnswerCallUpstreamTask : public CommandTask
+{
+public:
+ AnswerCallUpstreamTask ();
+protected:
+ virtual int process (Command *command);
+};
+// Listing 013
+
+// Listing 02 code/ch18
+class RetrieveCallerIdModule : public CommandModule
+{
+public:
+ RetrieveCallerIdModule (ACE_SOCK_Stream *peer);
+};
+class RetrieveCallerIdDownstreamTask : public CommandTask
+{
+public:
+ RetrieveCallerIdDownstreamTask ();
+protected:
+ virtual int process (Command *command);
+};
+class RetrieveCallerIdUpstreamTask : public CommandTask
+{
+public:
+ RetrieveCallerIdUpstreamTask ();
+protected:
+ virtual int process (Command *command);
+};
+// Listing 02
+
+// Listing 03 code/ch18
+class PlayMessageModule : public CommandModule
+{
+public:
+ PlayMessageModule (ACE_SOCK_Stream *peer);
+};
+class PlayMessageDownstreamTask : public CommandTask
+{
+public:
+ PlayMessageDownstreamTask ();
+protected:
+ virtual int process (Command *command);
+};
+class PlayMessageUpstreamTask : public CommandTask
+{
+public:
+ PlayMessageUpstreamTask ();
+protected:
+ virtual int process (Command *command);
+};
+// Listing 03
+
+// Listing 04 code/ch18
+class RecordMessageModule : public CommandModule
+{
+public:
+ RecordMessageModule (ACE_SOCK_Stream *peer);
+};
+class RecordMessageDownstreamTask : public CommandTask
+{
+public:
+ RecordMessageDownstreamTask ();
+protected:
+ virtual int process (Command *command);
+};
+class RecordMessageUpstreamTask : public CommandTask
+{
+public:
+ RecordMessageUpstreamTask ();
+protected:
+ virtual int process (Command *command);
+};
+// Listing 04
+
+#endif /* COMMAND_TASKS_H */
diff --git a/ACE/examples/APG/Streams/EndTask.h b/ACE/examples/APG/Streams/EndTask.h
new file mode 100644
index 00000000000..a42eca655d9
--- /dev/null
+++ b/ACE/examples/APG/Streams/EndTask.h
@@ -0,0 +1,27 @@
+/* -*- C++ -*- */
+// $Id$
+
+#ifndef END_TASK_H
+#define END_TASK_H
+
+// Listing 1 code/ch18
+class EndTask : public BasicTask {
+protected:
+ virtual int process (Message *)
+ {
+ ACE_TRACE (ACE_TEXT ("EndTask::process()"));
+ return 0;
+ }
+
+ virtual int next_step (ACE_Message_Block *mb)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("EndTask::next_step() - ")
+ ACE_TEXT ("end of the line.\n")));
+ mb->release ();
+ return 0;
+ }
+};
+// Listing 1
+
+#endif /* END_TASK_H */
diff --git a/ACE/examples/APG/Streams/Makefile.am b/ACE/examples/APG/Streams/Makefile.am
new file mode 100644
index 00000000000..e23f2f22143
--- /dev/null
+++ b/ACE/examples/APG/Streams/Makefile.am
@@ -0,0 +1,52 @@
+## Process this file with automake to create Makefile.in
+##
+## $Id$
+##
+## This file was generated by MPC. Any changes made directly to
+## this file will be lost the next time it is generated.
+##
+## MPC Command:
+## /acebuilds/ACE_wrappers-repository/bin/mwc.pl -include /acebuilds/MPC/config -include /acebuilds/MPC/templates -feature_file /acebuilds/ACE_wrappers-repository/local.features -noreldefs -type automake -exclude build,Kokyu
+
+ACE_BUILDDIR = $(top_builddir)
+ACE_ROOT = $(top_srcdir)
+
+
+## Makefile.Answerer.am
+
+if BUILD_THREADS
+if !BUILD_ACE_FOR_TAO
+noinst_PROGRAMS = Answerer
+
+Answerer_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+Answerer_SOURCES = \
+ Answerer.cpp \
+ CommandModule.cpp \
+ CommandStream.cpp \
+ CommandTask.cpp \
+ CommandTasks.cpp \
+ RecordingDeviceFactory.cpp \
+ RecordingDevice_Text.cpp \
+ CommandModule.h \
+ CommandStream.h \
+ CommandTask.h \
+ CommandTasks.h \
+ RecordingDeviceFactory.h \
+ RecordingDevice_Text.h
+
+Answerer_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+endif !BUILD_ACE_FOR_TAO
+endif BUILD_THREADS
+
+## Clean up template repositories, etc.
+clean-local:
+ -rm -f *~ *.bak *.rpo *.sym lib*.*_pure_* core core.*
+ -rm -f gcctemp.c gcctemp so_locations *.ics
+ -rm -rf cxx_repository ptrepository ti_files
+ -rm -rf templateregistry ir.out
+ -rm -rf ptrepository SunWS_cache Templates.DB
diff --git a/ACE/examples/APG/Streams/Message.h b/ACE/examples/APG/Streams/Message.h
new file mode 100644
index 00000000000..29ddd30d5a1
--- /dev/null
+++ b/ACE/examples/APG/Streams/Message.h
@@ -0,0 +1,92 @@
+/* -*- C++ -*- */
+// $Id$
+
+#ifndef MESSAGE_H
+#define MESSAGE_H
+
+class RecordingDevice;
+
+class Message
+{
+public:
+ Message () : device_(0), type_(0), id_(0)
+ { }
+
+ ~Message ()
+ { }
+
+ RecordingDevice *recorder (void)
+ {
+ return this->device_;
+ }
+
+ void recorder (RecordingDevice *device)
+ {
+ this->device_ = device;
+ }
+
+ void type (MessageType *type)
+ {
+ this->type_ = type;
+ }
+
+ MessageType *type (void)
+ {
+ return this->type_;
+ }
+
+ void caller_id (CallerId *id)
+ {
+ this->id_ = id;
+ }
+
+ CallerId *caller_id (void)
+ {
+ return this->id_;
+ }
+
+ void addr (ACE_FILE_Addr &addr)
+ {
+ this->addr_ = addr;
+ }
+
+ void incoming_message (ACE_FILE_Addr &addr, MessageType *type)
+ {
+ this->addr_ = addr;
+ this->type_ = type;
+ }
+
+ ACE_FILE_Addr &addr (void)
+ {
+ return this->addr_;
+ }
+
+ int is_text (void)
+ {
+ return this->type_->is_text ();
+ }
+
+ int is_audio (void)
+ {
+ return this->type_->is_audio ();
+ }
+
+ int is_video (void)
+ {
+ return this->type_->is_video ();
+ }
+
+private:
+ RecordingDevice *device_;
+ MessageType *type_;
+ CallerId *id_;
+ ACE_FILE_Addr addr_;
+};
+
+class AudioMessage : public Message
+{ };
+
+class VideoMessage : public Message
+{ };
+
+#endif /* MESSAGE_H */
diff --git a/ACE/examples/APG/Streams/MessageInfo.h b/ACE/examples/APG/Streams/MessageInfo.h
new file mode 100644
index 00000000000..0f0f1bc60dc
--- /dev/null
+++ b/ACE/examples/APG/Streams/MessageInfo.h
@@ -0,0 +1,100 @@
+/* -*- C++ -*- */
+// $Id$
+
+#ifndef MESSAGE_INFO_H
+#define MESSAGE_INFO_H
+
+#include "ace/FILE_Addr.h"
+#include "ace/SString.h"
+
+/* Opaque class that represents a caller's ID */
+class CallerId
+{
+public:
+ CallerId () : id_ (ACE_TEXT ("UNKNOWN"))
+ { }
+
+ CallerId (ACE_TString id) : id_(id)
+ { }
+
+ const ACE_TCHAR * string(void)
+ {
+ return this->id_.c_str ();
+ }
+
+private:
+ ACE_TString id_;
+};
+
+class MessageType
+{
+public:
+ enum {
+ // Known video codecs
+ FIRST_VIDEO_CODEC = 1,
+
+ DIVX,
+ // ...
+ LAST_VIDEO_CODEC,
+
+ // Known audio codecs
+ FIRST_AUDIO_CODEC,
+
+ MP3,
+ RAWPCM,
+ // ...
+ LAST_AUDIO_CODEC,
+
+ // Known text codecs
+ FIRST_TEXT_CODEC,
+
+ RAWTEXT,
+ XML,
+
+ // ...
+ LAST_TEXT_CODEC,
+
+ LAST_CODEC
+ };
+
+ MessageType (int codec, ACE_FILE_Addr addr)
+ : codec_(codec), addr_(addr)
+ { }
+
+ int get_codec (void)
+ {
+ return this->codec_;
+ }
+
+ ACE_FILE_Addr &get_addr (void)
+ {
+ return this->addr_;
+ }
+
+ int is_video (void)
+ {
+ return
+ this->get_codec () > FIRST_VIDEO_CODEC &&
+ this->get_codec () < LAST_VIDEO_CODEC;
+ }
+
+ int is_audio (void)
+ {
+ return
+ this->get_codec () > FIRST_AUDIO_CODEC &&
+ this->get_codec () < LAST_AUDIO_CODEC ;
+ }
+
+ int is_text (void)
+ {
+ return
+ this->get_codec () > FIRST_TEXT_CODEC &&
+ this->get_codec () < LAST_TEXT_CODEC ;
+ }
+
+private:
+ int codec_;
+ ACE_FILE_Addr addr_;
+};
+
+# endif /* MESSAGE_INFO_H */
diff --git a/ACE/examples/APG/Streams/RecordingDevice.h b/ACE/examples/APG/Streams/RecordingDevice.h
new file mode 100644
index 00000000000..cee3d7154de
--- /dev/null
+++ b/ACE/examples/APG/Streams/RecordingDevice.h
@@ -0,0 +1,119 @@
+/* -*- C++ -*- */
+// $Id$
+
+#ifndef RECORDING_DEVICE_H
+#define RECORDING_DEVICE_H
+
+#include "ace/FILE_Addr.h"
+#include "ace/Event_Handler.h"
+#include "ace/Log_Msg.h"
+#include "ace/Reactor.h"
+#include "ace/Semaphore.h"
+
+class CallerId;
+class MessageType;
+
+class RecordingDevice
+{
+public:
+ RecordingDevice ()
+ {
+ // Initialize the semaphore so that we don't block on the
+ // first call to wait_for_activity().
+ }
+
+ virtual ~RecordingDevice ()
+ {
+ }
+
+ virtual const ACE_TCHAR *get_name (void) const
+ {
+ return ACE_TEXT ("UNKNOWN");
+ }
+
+ virtual int init (int, ACE_TCHAR *[])
+ {
+ return 0;
+ }
+
+ // Answer the incoming call
+ virtual int answer_call (void) = 0;
+
+ // Fetch some form of caller identification at the hardware level.
+ virtual CallerId *retrieve_callerId (void) = 0;
+
+ // Fetch the message at the location specified by 'addr' and play
+ // it for the caller.
+ virtual int play_message (ACE_FILE_Addr &addr) = 0;
+
+ // Record data from our physical device into the file at the
+ // specified address. Return the number of bytes recorded.
+ virtual MessageType *record_message (ACE_FILE_Addr &addr) = 0;
+
+ // Release the RecordingDevice to accept another incoming call
+ virtual void release (void)
+ {
+ this->release_semaphore ();
+ }
+
+ // Get the handler of the device so that wait_for_activity() can
+ // wait for data to arrive.
+ virtual ACE_Event_Handler *get_handler (void) const
+ {
+ return 0;
+ }
+
+ virtual RecordingDevice *wait_for_activity (void)
+ {
+ // Block on a semaphore until it says we're ready to do
+ // work.
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("Waiting for semaphore\n")));
+ this->acquire_semaphore ();
+
+ // Use the reactor to wait for activity on our handle
+ ACE_Reactor reactor;
+
+ ACE_Event_Handler *handler = this->get_handler ();
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("Handler is %@\n"),
+ (void *)handler));
+
+ reactor.register_handler (this->get_handler (),
+ ACE_Event_Handler::READ_MASK);
+
+ reactor.handle_events ();
+ // Error-check this...
+
+ // Leave the semaphore locked so that we'll block until
+ // recording_complete() is invoked.
+
+ return this;
+ }
+
+protected:
+ void acquire_semaphore (void)
+ {
+ this->semaphore_.acquire ();
+ }
+
+ void release_semaphore (void)
+ {
+ // Reset the semaphore so that wait_for_activity() will
+ // unblock.
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("Releasing semaphore\n")));
+ this->semaphore_.release ();
+ }
+
+private:
+ ACE_Semaphore semaphore_;
+};
+
+#include "RecordingDevice_Text.h"
+#include "RecordingDevice_USRVM.h"
+#include "RecordingDevice_QC.h"
+
+#include "RecordingDeviceFactory.h"
+
+#endif /* RECORDING_DEVICE_H */
diff --git a/ACE/examples/APG/Streams/RecordingDeviceFactory.cpp b/ACE/examples/APG/Streams/RecordingDeviceFactory.cpp
new file mode 100644
index 00000000000..f5585e1ec0a
--- /dev/null
+++ b/ACE/examples/APG/Streams/RecordingDeviceFactory.cpp
@@ -0,0 +1,25 @@
+// $Id$
+
+#include "RecordingDevice.h"
+#include "RecordingDeviceFactory.h"
+#include "RecordingDevice_Text.h"
+
+RecordingDevice *RecordingDeviceFactory::instantiate (int argc,
+ ACE_TCHAR *argv[])
+{
+ RecordingDevice * device = 0;
+
+ // Determine the implementation based on the values of argv
+ // Exclude 2
+ device = new TextListenerAcceptor ();
+ // Exclude 2
+
+ // Initialize the device with the remaining parameters.
+ if (device->init (argc, argv) < 0)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("RecordingDeviceFactory::instantiate() - ")
+ ACE_TEXT ("%s->init(argc, argv)"),
+ device->get_name()),
+ 0);
+ return device;
+}
diff --git a/ACE/examples/APG/Streams/RecordingDeviceFactory.h b/ACE/examples/APG/Streams/RecordingDeviceFactory.h
new file mode 100644
index 00000000000..13485b20947
--- /dev/null
+++ b/ACE/examples/APG/Streams/RecordingDeviceFactory.h
@@ -0,0 +1,22 @@
+/* -*- C++ -*- */
+// $Id$
+
+#ifndef RECORDING_DEVICE_FACTORY_H
+#define RECORDING_DEVICE_FACTORY_H
+
+class RecordingDevice;
+
+/*
+ * A factory class that creates an appropriate RecordingDevice
+ * derivative based on command-line parameters.
+ */
+class RecordingDeviceFactory
+{
+public:
+
+ // Instantiate the appropriate RecordingDevice implementation
+ static RecordingDevice *instantiate (int argc, ACE_TCHAR *argv[]);
+};
+
+#endif /* RECORDING_DEVICE_FACTORY_H */
+
diff --git a/ACE/examples/APG/Streams/RecordingDevice_QC.h b/ACE/examples/APG/Streams/RecordingDevice_QC.h
new file mode 100644
index 00000000000..356d70afc5c
--- /dev/null
+++ b/ACE/examples/APG/Streams/RecordingDevice_QC.h
@@ -0,0 +1,5 @@
+// $Id$
+
+class QuickCam : public RecordingDevice
+ {
+ };
diff --git a/ACE/examples/APG/Streams/RecordingDevice_Text.cpp b/ACE/examples/APG/Streams/RecordingDevice_Text.cpp
new file mode 100644
index 00000000000..01720bb2470
--- /dev/null
+++ b/ACE/examples/APG/Streams/RecordingDevice_Text.cpp
@@ -0,0 +1,197 @@
+/*
+ * $Id$
+ *
+ * A RecordingDevice that listens to a socket and collects text.
+ */
+
+#include "MessageInfo.h"
+#include "RecordingDevice.h"
+#include "RecordingDevice_Text.h"
+#include "Util.h"
+
+TextListenerAcceptor::TextListenerAcceptor (void)
+ : ACE_Event_Handler(), RecordingDevice()
+{ }
+
+// ACE_Event_Handler interface
+
+int TextListenerAcceptor::open (ACE_INET_Addr &addr)
+{
+ if (this->acceptor_.open (addr, 1) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("acceptor open")),
+ -1);
+ return 0;
+}
+
+ACE_HANDLE TextListenerAcceptor::get_handle (void) const
+{
+ return this->acceptor_.get_handle ();
+}
+
+int TextListenerAcceptor::handle_input (ACE_HANDLE)
+{
+ ACE_DEBUG ((LM_INFO,
+ ACE_TEXT ("TextListenerAcceptor - connection request\n" )));
+ return 0;
+}
+
+int TextListenerAcceptor::accept (ACE_SOCK_Stream &peer)
+{
+ return this->acceptor_.accept (peer);
+}
+
+// RecordingDevice interface
+
+// Open a listening socket on the port specified by argv.
+int TextListenerAcceptor::init (int argc, ACE_TCHAR *argv[])
+{
+ ACE_UNUSED_ARG(argc);
+
+ ACE_INET_Addr addr (argv[1]);
+
+ if (this->open (addr) < 0)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("TextListener - open")),
+ -1);
+ return 0;
+}
+
+ACE_Event_Handler *TextListenerAcceptor::get_handler (void) const
+{
+ return (ACE_Event_Handler *)this;
+}
+
+RecordingDevice *TextListenerAcceptor::wait_for_activity (void)
+{
+ this->RecordingDevice::wait_for_activity ();
+ return new TextListener (this);
+}
+
+int TextListenerAcceptor::answer_call (void)
+{
+ return -1;
+}
+
+CallerId *TextListenerAcceptor::retrieve_callerId (void)
+{
+ return 0;
+}
+
+int TextListenerAcceptor::play_message (ACE_FILE_Addr &addr)
+{
+ ACE_UNUSED_ARG(addr);
+ return 0;
+}
+
+MessageType *TextListenerAcceptor::record_message (ACE_FILE_Addr &addr)
+{
+ ACE_UNUSED_ARG(addr);
+ return 0;
+}
+
+
+// Listing 01 code/ch18
+TextListener::TextListener (TextListenerAcceptor *acceptor)
+ : acceptor_(acceptor)
+{
+ ACE_TRACE ("TextListener ctor");
+
+ ACE_NEW (this->command_stream_, CommandStream (&(this->peer_)));
+ this->command_stream_->open (0);
+}
+// Listing 01
+
+const ACE_TCHAR *TextListener::get_name (void) const
+{
+ return ACE_TEXT ("TextListener");
+}
+
+// Listing 02 code/ch18
+int TextListener::answer_call (void)
+{
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("TextListener::answer_call()\n")));
+
+ Command *c = new Command ();
+ c->command_ = Command::CMD_ANSWER_CALL;
+ c->extra_data_ = this->acceptor_;
+
+ c = this->command_stream_->execute (c);
+
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("TextListener::answer_call() ")
+ ACE_TEXT ("result is %d\n"),
+ c->numeric_result_));
+
+ return c->numeric_result_;
+}
+// Listing 02
+
+// Listing 03 code/ch18
+CallerId *TextListener::retrieve_callerId (void)
+{
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("TextListener::retrieve_callerId()\n")));
+
+ Command *c = new Command ();
+ c->command_ = Command::CMD_RETRIEVE_CALLER_ID;
+
+ c = this->command_stream_->execute (c);
+
+ CallerId *caller_id = new CallerId (c->result_);
+ return caller_id;
+}
+// Listing 03
+
+// Listing 04 code/ch18
+int TextListener::play_message (ACE_FILE_Addr &addr)
+{
+ MessageType *type = Util::identify_message (addr);
+ if (type->is_text ())
+ {
+ Command *c = new Command ();
+ c->command_ = Command::CMD_PLAY_MESSAGE;
+ c->extra_data_ = &addr;
+ c = this->command_stream_->execute (c);
+ return c->numeric_result_;
+ }
+
+ ACE_FILE_Addr temp (ACE_TEXT ("/tmp/outgoing_message.text"));
+ ACE_FILE_IO *file;
+ if (type->is_audio ())
+ file = Util::audio_to_text (addr, temp);
+ else if (type->is_video ())
+ file = Util::video_to_text (addr, temp);
+ else
+ ACE_ERROR_RETURN
+ ((LM_ERROR, ACE_TEXT ("Invalid message type %d\n"),
+ type->get_codec ()), -1);
+ int rval = this->play_message (temp);
+ file->remove ();
+ return rval;
+}
+// Listing 04
+
+// Listing 05 code/ch18
+MessageType *TextListener::record_message (ACE_FILE_Addr &addr)
+{
+ Command *c = new Command ();
+ c->command_ = Command::CMD_RECORD_MESSAGE;
+ c->extra_data_ = &addr;
+ c = this->command_stream_->execute (c);
+ if (c->numeric_result_ == -1)
+ return 0;
+
+ return new MessageType (MessageType::RAWTEXT, addr);
+}
+// Listing 05
+
+// Listing 06 code/ch18
+void TextListener::release (void)
+{
+ delete this;
+}
+// Listing 06
diff --git a/ACE/examples/APG/Streams/RecordingDevice_Text.h b/ACE/examples/APG/Streams/RecordingDevice_Text.h
new file mode 100644
index 00000000000..a49f400d922
--- /dev/null
+++ b/ACE/examples/APG/Streams/RecordingDevice_Text.h
@@ -0,0 +1,84 @@
+/* -*- C++ -*- */
+/*
+ * $Id$
+ *
+ * A RecordingDevice that listens to a socket and collects text.
+ */
+
+#ifndef RECORDING_DEVICE_TEXT_H
+#define RECORDING_DEVICE_TEXT_H
+
+#include "ace/FILE_IO.h"
+#include "ace/FILE_Connector.h"
+#include "ace/SOCK_Stream.h"
+#include "ace/SOCK_Acceptor.h"
+
+#include "CommandStream.h"
+#include "MessageInfo.h"
+#include "RecordingDevice.h"
+
+class TextListenerAcceptor :
+ public ACE_Event_Handler,
+ public RecordingDevice
+{
+public:
+ TextListenerAcceptor ();
+
+ // ACE_Event_Handler interface
+
+ int open (ACE_INET_Addr &addr);
+
+ ACE_HANDLE get_handle (void) const;
+
+ int handle_input (ACE_HANDLE);
+
+ int accept (ACE_SOCK_Stream &peer);
+
+ // RecordingDevice interface
+
+ // Open a listening socket on the port specified by argv.
+ int init (int argc, ACE_TCHAR *argv[]);
+
+ ACE_Event_Handler *get_handler (void) const;
+
+ virtual RecordingDevice *wait_for_activity (void);
+
+ virtual int answer_call (void);
+
+ virtual CallerId *retrieve_callerId (void);
+
+ virtual int play_message (ACE_FILE_Addr &addr);
+
+ virtual MessageType *record_message (ACE_FILE_Addr &addr);
+
+private:
+ ACE_SOCK_Acceptor acceptor_;
+};
+
+// Listing 01 code/ch18
+class TextListener : public RecordingDevice
+{
+public:
+ TextListener (TextListenerAcceptor *acceptor);
+
+ virtual const ACE_TCHAR *get_name (void) const;
+
+ int answer_call (void);
+
+ CallerId *retrieve_callerId (void);
+
+ int play_message (ACE_FILE_Addr &addr);
+
+ MessageType *record_message (ACE_FILE_Addr &addr);
+
+ virtual void release (void);
+ // Listing 01
+ // Listing 02 code/ch18
+private:
+ CommandStream *command_stream_;
+ TextListenerAcceptor *acceptor_;
+ ACE_SOCK_Stream peer_;
+};
+// Listing 02
+
+#endif /* RECORDING_DEVICE_TEXT_H */
diff --git a/ACE/examples/APG/Streams/RecordingDevice_USRVM.h b/ACE/examples/APG/Streams/RecordingDevice_USRVM.h
new file mode 100644
index 00000000000..7519f7c1c84
--- /dev/null
+++ b/ACE/examples/APG/Streams/RecordingDevice_USRVM.h
@@ -0,0 +1,5 @@
+// $Id$
+
+class USRoboticsVoiceModem : public RecordingDevice
+ {
+ };
diff --git a/ACE/examples/APG/Streams/Util.h b/ACE/examples/APG/Streams/Util.h
new file mode 100644
index 00000000000..d47a699aee7
--- /dev/null
+++ b/ACE/examples/APG/Streams/Util.h
@@ -0,0 +1,92 @@
+/* -*- C++ -*- */
+// $Id$
+
+#ifndef UTIL_H
+#define UTIL_H
+
+#include "ace/FILE_Addr.h"
+#include "ace/FILE_Connector.h"
+#include "ace/FILE_IO.h"
+
+class Util
+{
+public:
+ static MessageType *identify_message (ACE_FILE_Addr &src)
+ {
+ // Determine the contents of the specified file
+ return new MessageType (MessageType::RAWTEXT, src);
+ }
+
+ static ACE_FILE_IO *audio_to_text (ACE_FILE_Addr &, ACE_FILE_Addr &dest)
+ {
+ ACE_FILE_Connector connector;
+ ACE_FILE_IO *file = 0;
+ if (connector.connect (*file, dest) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("create file")),
+ 0);
+
+ // Convert audio data to printable text
+
+ return file;
+ }
+
+ static ACE_FILE_IO *video_to_text (ACE_FILE_Addr &, ACE_FILE_Addr &dest)
+ {
+ ACE_FILE_Connector connector;
+ ACE_FILE_IO *file = 0;
+ if (connector.connect (*file, dest) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("create file")),
+ 0);
+
+ // Extract audio data from video file and convert to printable text
+ return file;
+ }
+
+ static int convert_to_unicode (ACE_FILE_Addr &src, ACE_FILE_Addr &dest)
+ {
+ ACE_FILE_Connector connector;
+ ACE_FILE_IO input;
+ if (connector.connect (input, src) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("read file")),
+ 0);
+ ACE_FILE_IO output;
+ if (connector.connect (output, dest) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("create file")),
+ 0);
+
+ char rwbuf[512];
+ ssize_t rwbytes;
+ while ((rwbytes = input.recv (rwbuf, 512)) > 0)
+ {
+ output.send_n (rwbuf, rwbytes);
+ }
+
+ input.close ();
+ output.close ();
+
+ // Convert arbirary text to unicode
+ return 0;
+ }
+
+ static int convert_to_mp3 (ACE_FILE_Addr &, ACE_FILE_Addr &)
+ {
+ // Convert arbitrary audio data to some standard mp3 format
+ return 0;
+ }
+
+ static int convert_to_mpeg (ACE_FILE_Addr &, ACE_FILE_Addr &)
+ {
+ // Convert arbitrary vidio data to some standard mpeg format
+ return 0;
+ }
+};
+
+#endif /* UTIL_H */
diff --git a/ACE/examples/APG/Streams/streams.mpc b/ACE/examples/APG/Streams/streams.mpc
new file mode 100644
index 00000000000..df74b446031
--- /dev/null
+++ b/ACE/examples/APG/Streams/streams.mpc
@@ -0,0 +1,17 @@
+// -*- MPC -*-
+// $Id$
+
+project(Answerer) : aceexe {
+ avoids += ace_for_tao
+ exename = Answerer
+ requires += threads
+ Source_Files {
+ Answerer.cpp
+ CommandModule.cpp
+ CommandStream.cpp
+ CommandTask.cpp
+ CommandTasks.cpp
+ RecordingDeviceFactory.cpp
+ RecordingDevice_Text.cpp
+ }
+}
diff --git a/ACE/examples/APG/Svc_Config/.cvsignore b/ACE/examples/APG/Svc_Config/.cvsignore
new file mode 100644
index 00000000000..c508d301216
--- /dev/null
+++ b/ACE/examples/APG/Svc_Config/.cvsignore
@@ -0,0 +1,4 @@
+HA_Configurable_Server_Dynamic
+HA_Configurable_Server_Dynamic
+HA_Configurable_Server_Static
+HA_Configurable_Server_Static
diff --git a/ACE/examples/APG/Svc_Config/HASTATUS_export.h b/ACE/examples/APG/Svc_Config/HASTATUS_export.h
new file mode 100644
index 00000000000..9115c514089
--- /dev/null
+++ b/ACE/examples/APG/Svc_Config/HASTATUS_export.h
@@ -0,0 +1,53 @@
+// -*- C++ -*-
+// $Id$
+// Definition for Win32 Export directives.
+// This file is generated automatically by generate_export_file.pl HASTATUS
+// ------------------------------
+#ifndef HASTATUS_EXPORT_H
+#define HASTATUS_EXPORT_H
+
+#include "ace/config-all.h"
+
+#if defined (ACE_AS_STATIC_LIBS) && !defined (HASTATUS_HAS_DLL)
+# define HASTATUS_HAS_DLL 0
+#endif /* ACE_AS_STATIC_LIBS && ! HASTATUS_HAS_DLL */
+
+#if !defined (HASTATUS_HAS_DLL)
+# define HASTATUS_HAS_DLL 1
+#endif /* ! HASTATUS_HAS_DLL */
+
+#if defined (HASTATUS_HAS_DLL) && (HASTATUS_HAS_DLL == 1)
+# if defined (HASTATUS_BUILD_DLL)
+# define HASTATUS_Export ACE_Proper_Export_Flag
+# define HASTATUS_SINGLETON_DECLARATION(T) ACE_EXPORT_SINGLETON_DECLARATION (T)
+# define HASTATUS_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) ACE_EXPORT_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK)
+# else /* HASTATUS_BUILD_DLL */
+# define HASTATUS_Export ACE_Proper_Import_Flag
+# define HASTATUS_SINGLETON_DECLARATION(T) ACE_IMPORT_SINGLETON_DECLARATION (T)
+# define HASTATUS_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) ACE_IMPORT_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK)
+# endif /* HASTATUS_BUILD_DLL */
+#else /* HASTATUS_HAS_DLL == 1 */
+# define HASTATUS_Export
+# define HASTATUS_SINGLETON_DECLARATION(T)
+# define HASTATUS_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK)
+#endif /* HASTATUS_HAS_DLL == 1 */
+
+// Set HASTATUS_NTRACE = 0 to turn on library specific tracing even if
+// tracing is turned off for ACE.
+#if !defined (HASTATUS_NTRACE)
+# if (ACE_NTRACE == 1)
+# define HASTATUS_NTRACE 1
+# else /* (ACE_NTRACE == 1) */
+# define HASTATUS_NTRACE 0
+# endif /* (ACE_NTRACE == 1) */
+#endif /* !HASTATUS_NTRACE */
+
+#if (HASTATUS_NTRACE == 1)
+# define HASTATUS_TRACE(X)
+#else /* (HASTATUS_NTRACE == 1) */
+# define HASTATUS_TRACE(X) ACE_TRACE _IMPL(X)
+#endif /* (HASTATUS_NTRACE == 1) */
+
+#endif /* HASTATUS_EXPORT_H */
+
+// End of auto generated file.
diff --git a/ACE/examples/APG/Svc_Config/HA_Configurable_Server_Dynamic.cpp b/ACE/examples/APG/Svc_Config/HA_Configurable_Server_Dynamic.cpp
new file mode 100644
index 00000000000..1126a0393d1
--- /dev/null
+++ b/ACE/examples/APG/Svc_Config/HA_Configurable_Server_Dynamic.cpp
@@ -0,0 +1,17 @@
+// $Id$
+
+// Listing 1 code/ch19
+#include "ace/OS_main.h"
+#include "ace/Service_Config.h"
+#include "ace/Reactor.h"
+
+int ACE_TMAIN (int argc, ACE_TCHAR *argv[])
+{
+ ACE_Service_Config::open (argc, argv);
+
+ // We use this version of the event loop so that reconfigurations
+ // are triggered properly.
+ ACE_Reactor::instance ()->run_reactor_event_loop (ACE_Reactor::check_reconfiguration);
+ return 0;
+}
+// Listing 1
diff --git a/ACE/examples/APG/Svc_Config/HA_Configurable_Server_Static.cpp b/ACE/examples/APG/Svc_Config/HA_Configurable_Server_Static.cpp
new file mode 100644
index 00000000000..8ac10b08ee1
--- /dev/null
+++ b/ACE/examples/APG/Svc_Config/HA_Configurable_Server_Static.cpp
@@ -0,0 +1,18 @@
+// $Id$
+
+// Listing 1 code/ch19
+#include "ace/OS_main.h"
+#include "ace/Service_Config.h"
+#include "ace/Reactor.h"
+
+int ACE_TMAIN (int argc, ACE_TCHAR *argv[])
+{
+ ACE_STATIC_SVC_REGISTER (HA_Status_Descriptor);
+ ACE_Service_Config::open (argc,
+ argv,
+ ACE_DEFAULT_LOGGER_KEY,
+ 0);
+ ACE_Reactor::instance ()->run_reactor_event_loop ();
+ return 0;
+}
+// Listing 1
diff --git a/ACE/examples/APG/Svc_Config/HA_Status_Dynamic.cpp b/ACE/examples/APG/Svc_Config/HA_Status_Dynamic.cpp
new file mode 100644
index 00000000000..39f871a8bb3
--- /dev/null
+++ b/ACE/examples/APG/Svc_Config/HA_Status_Dynamic.cpp
@@ -0,0 +1,113 @@
+/**
+ * $Id$
+ *
+ * Home Automation Status server. Sample code from The ACE Programmer's Guide,
+ * Copyright 2003 Addison-Wesley. All Rights Reserved.
+ */
+
+#include "ace/OS_NS_stdio.h"
+#include "ace/OS_NS_string.h"
+#include "ace/Configuration.h"
+#include "ace/Configuration_Import_Export.h"
+#include "ace/Get_Opt.h"
+#include "HA_Status_Dynamic.h"
+
+// Listing 1 code/ch19
+int
+HA_Status::init (int argc, ACE_TCHAR *argv[])
+{
+ static const ACE_TCHAR options[] = ACE_TEXT (":f:");
+ ACE_Get_Opt cmd_opts (argc, argv, options, 0);
+ if (cmd_opts.long_option
+ (ACE_TEXT ("config"), 'f', ACE_Get_Opt::ARG_REQUIRED) == -1)
+ return -1;
+ int option;
+ ACE_TCHAR config_file[MAXPATHLEN];
+ ACE_OS::strcpy (config_file, ACE_TEXT ("HAStatus.conf"));
+ while ((option = cmd_opts ()) != EOF)
+ switch (option)
+ {
+ case 'f':
+ ACE_OS::strncpy (config_file,
+ cmd_opts.opt_arg (),
+ MAXPATHLEN);
+ break;
+ case ':':
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("-%c requires an argument\n"),
+ cmd_opts.opt_opt ()),
+ -1);
+ default:
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("Parse error.\n")),
+ -1);
+ }
+
+ ACE_Configuration_Heap config;
+ config.open ();
+ ACE_Registry_ImpExp config_importer (config);
+ if (config_importer.import_config (config_file) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ config_file),
+ -1);
+
+ ACE_Configuration_Section_Key status_section;
+ if (config.open_section (config.root_section (),
+ ACE_TEXT ("HAStatus"),
+ 0,
+ status_section) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("Can't open HAStatus section")),
+ -1);
+
+ u_int status_port;
+ if (config.get_integer_value (status_section,
+ ACE_TEXT ("ListenPort"),
+ status_port) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("HAStatus ListenPort ")
+ ACE_TEXT ("does not exist\n")),
+ -1);
+ this->listen_addr_.set (static_cast<u_short> (status_port));
+
+ if (this->acceptor_.open (this->listen_addr_) != 0)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("HAStatus %p\n"),
+ ACE_TEXT ("accept")),
+ -1);
+
+ return 0;
+}
+// Listing 1
+
+// Listing 2 code/ch19
+int
+HA_Status::fini (void)
+{
+ this->acceptor_.close ();
+ return 0;
+}
+// Listing 2
+
+// Listing 3 code/ch19
+int
+HA_Status::info (ACE_TCHAR **str, size_t len) const
+ {
+ ACE_TCHAR buf[BUFSIZ];
+ ACE_OS::sprintf (buf,
+ ACE_TEXT ("HAStatus listening on port %hu\n"),
+ this->listen_addr_.get_port_number ());
+ if (*str == 0)
+ *str = ACE::strnew (buf);
+ else
+ ACE_OS::strncpy (*str, buf, len);
+ return static_cast<int> (ACE_OS::strlen (*str));
+ }
+// Listing 3
+
+// Listing 4 code/ch19
+ACE_FACTORY_DEFINE (HASTATUS, HA_Status)
+// Listing 4
+
diff --git a/ACE/examples/APG/Svc_Config/HA_Status_Dynamic.h b/ACE/examples/APG/Svc_Config/HA_Status_Dynamic.h
new file mode 100644
index 00000000000..c11f9a56d35
--- /dev/null
+++ b/ACE/examples/APG/Svc_Config/HA_Status_Dynamic.h
@@ -0,0 +1,43 @@
+/**
+ * $Id$
+ *
+ * Home Automation Status server. Sample code from The ACE Programmer's Guide,
+ * copyright 2003 Addison-Wesley. All Rights Reserved.
+ */
+
+#ifndef __HASTATUS_H_
+#define __HASTATUS_H_
+
+// Listing 1 code/ch19
+#include "ace/OS.h"
+#include "ace/Acceptor.h"
+#include "ace/INET_Addr.h"
+#include "ace/SOCK_Stream.h"
+#include "ace/SOCK_Acceptor.h"
+#include "ace/Service_Object.h"
+#include "ace/Svc_Handler.h"
+
+#include "HASTATUS_export.h"
+
+class ClientHandler :
+ public ACE_Svc_Handler<ACE_SOCK_STREAM, ACE_NULL_SYNCH>
+{
+ // ... Same as previous examples.
+};
+
+class HASTATUS_Export HA_Status : public ACE_Service_Object
+{
+ public:
+ virtual int init (int argc, ACE_TCHAR *argv[]);
+
+ virtual int fini (void);
+
+ virtual int info (ACE_TCHAR **str, size_t len) const;
+
+ private:
+ ACE_Acceptor<ClientHandler, ACE_SOCK_ACCEPTOR> acceptor_;
+ ACE_INET_Addr listen_addr_;
+};
+// Listing 1
+
+#endif /* __HASTATUS_H_ */
diff --git a/ACE/examples/APG/Svc_Config/HA_Status_Static.cpp b/ACE/examples/APG/Svc_Config/HA_Status_Static.cpp
new file mode 100644
index 00000000000..ef09bcaa5cd
--- /dev/null
+++ b/ACE/examples/APG/Svc_Config/HA_Status_Static.cpp
@@ -0,0 +1,121 @@
+/**
+ * $Id$
+ *
+ * Home Automation Status server. Sample code from The ACE Programmer's Guide,
+ * Copyright 2003 Addison-Wesley. All Rights Reserved.
+ */
+
+#include "ace/OS_NS_stdio.h"
+#include "ace/OS_NS_string.h"
+#include "ace/Configuration.h"
+#include "ace/Configuration_Import_Export.h"
+#include "ace/Get_Opt.h"
+#include "HA_Status_Static.h"
+
+// Listing 1 code/ch19
+int
+HA_Status::init (int argc, ACE_TCHAR *argv[])
+{
+ static const ACE_TCHAR options[] = ACE_TEXT (":f:");
+ ACE_Get_Opt cmd_opts (argc, argv, options, 0);
+ if (cmd_opts.long_option
+ (ACE_TEXT ("config"), 'f', ACE_Get_Opt::ARG_REQUIRED) == -1)
+ return -1;
+ int option;
+ ACE_TCHAR config_file[MAXPATHLEN];
+ ACE_OS::strcpy (config_file, ACE_TEXT ("HAStatus.conf"));
+ while ((option = cmd_opts ()) != EOF)
+ switch (option)
+ {
+ case 'f':
+ ACE_OS::strncpy (config_file,
+ cmd_opts.opt_arg (),
+ MAXPATHLEN);
+ break;
+ case ':':
+ ACE_ERROR_RETURN
+ ((LM_ERROR, ACE_TEXT ("-%c requires an argument\n"),
+ cmd_opts.opt_opt ()),
+ -1);
+ default:
+ ACE_ERROR_RETURN
+ ((LM_ERROR, ACE_TEXT ("Parse error.\n")), -1);
+ }
+
+ ACE_Configuration_Heap config;
+ config.open ();
+ ACE_Registry_ImpExp config_importer (config);
+ if (config_importer.import_config (config_file) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ config_file),
+ -1);
+
+ ACE_Configuration_Section_Key status_section;
+ if (config.open_section (config.root_section (),
+ ACE_TEXT ("HAStatus"),
+ 0,
+ status_section) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("Can't open HAStatus section")),
+ -1);
+
+ u_int status_port;
+ if (config.get_integer_value (status_section,
+ ACE_TEXT ("ListenPort"),
+ status_port) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("HAStatus ListenPort does ")
+ ACE_TEXT ("not exist\n")),
+ -1);
+ this->listen_addr_.set (static_cast<u_short> (status_port));
+
+ if (this->acceptor_.open (this->listen_addr_) != 0)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("HAStatus %p\n"),
+ ACE_TEXT ("accept")),
+ -1);
+
+ return 0;
+}
+// Listing 1
+
+// Listing 2 code/ch19
+int
+HA_Status::fini (void)
+{
+ this->acceptor_.close ();
+ return 0;
+}
+// Listing 2
+
+// Listing 3 code/ch19
+int
+HA_Status::info (ACE_TCHAR **str, size_t len) const
+ {
+ ACE_TCHAR buf[BUFSIZ];
+ ACE_OS::sprintf (buf, ACE_TEXT ("HAStatus listening on port %hu\n"),
+ this->listen_addr_.get_port_number ());
+ if (*str == 0)
+ *str = ACE::strnew (buf);
+ else
+ ACE_OS::strncpy (*str, buf, len);
+ return static_cast<int> (ACE_OS::strlen (*str));
+ }
+// Listing 3
+
+// Listing 4 code/ch19
+ACE_FACTORY_DEFINE (ACE_Local_Service, HA_Status)
+
+ACE_STATIC_SVC_DEFINE (HA_Status_Descriptor,
+ ACE_TEXT ("HA_Status_Static_Service"),
+ ACE_SVC_OBJ_T,
+ &ACE_SVC_NAME (HA_Status),
+ ACE_Service_Type::DELETE_THIS |
+ ACE_Service_Type::DELETE_OBJ,
+ 0) // Service not initially active
+
+ACE_STATIC_SVC_REQUIRE (HA_Status_Descriptor)
+// Listing 4
+
diff --git a/ACE/examples/APG/Svc_Config/HA_Status_Static.h b/ACE/examples/APG/Svc_Config/HA_Status_Static.h
new file mode 100644
index 00000000000..d4926ff0460
--- /dev/null
+++ b/ACE/examples/APG/Svc_Config/HA_Status_Static.h
@@ -0,0 +1,40 @@
+/**
+ * $Id$
+ *
+ * Home Automation Status server. Sample code from The ACE Programmer's Guide,
+ * copyright 2003 Addison-Wesley. All Rights Reserved.
+ */
+
+#ifndef __HASTATUS_H_
+#define __HASTATUS_H_
+
+// Listing 1 code/ch19
+#include "ace/OS.h"
+#include "ace/Acceptor.h"
+#include "ace/INET_Addr.h"
+#include "ace/SOCK_Stream.h"
+#include "ace/SOCK_Acceptor.h"
+#include "ace/Service_Object.h"
+#include "ace/Svc_Handler.h"
+#include "ace/Service_Config.h"
+
+class ClientHandler :
+ public ACE_Svc_Handler<ACE_SOCK_STREAM, ACE_NULL_SYNCH>
+{
+ // ... Same as previous examples.
+};
+
+class HA_Status : public ACE_Service_Object
+{
+ public:
+ virtual int init (int argc, ACE_TCHAR *argv[]);
+ virtual int fini (void);
+ virtual int info (ACE_TCHAR **str, size_t len) const;
+
+ private:
+ ACE_Acceptor<ClientHandler, ACE_SOCK_ACCEPTOR> acceptor_;
+ ACE_INET_Addr listen_addr_;
+};
+// Listing 1
+
+#endif /* __HASTATUS_H_ */
diff --git a/ACE/examples/APG/Svc_Config/Makefile.am b/ACE/examples/APG/Svc_Config/Makefile.am
new file mode 100644
index 00000000000..9fa3e2f18b6
--- /dev/null
+++ b/ACE/examples/APG/Svc_Config/Makefile.am
@@ -0,0 +1,80 @@
+## Process this file with automake to create Makefile.in
+##
+## $Id$
+##
+## This file was generated by MPC. Any changes made directly to
+## this file will be lost the next time it is generated.
+##
+## MPC Command:
+## /acebuilds/ACE_wrappers-repository/bin/mwc.pl -include /acebuilds/MPC/config -include /acebuilds/MPC/templates -feature_file /acebuilds/ACE_wrappers-repository/local.features -noreldefs -type automake -exclude build,Kokyu
+
+ACE_BUILDDIR = $(top_builddir)
+ACE_ROOT = $(top_srcdir)
+
+noinst_PROGRAMS =
+
+## Makefile.HA_Configurable_Server_Dynamic.am
+
+if !BUILD_ACE_FOR_TAO
+noinst_PROGRAMS += HA_Configurable_Server_Dynamic
+
+HA_Configurable_Server_Dynamic_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+HA_Configurable_Server_Dynamic_SOURCES = \
+ HA_Configurable_Server_Dynamic.cpp \
+ HASTATUS_export.h \
+ HA_Status_Dynamic.h \
+ HA_Status_Static.h
+
+HA_Configurable_Server_Dynamic_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+endif !BUILD_ACE_FOR_TAO
+
+## Makefile.HA_Configurable_Server_Static.am
+
+if !BUILD_ACE_FOR_TAO
+noinst_PROGRAMS += HA_Configurable_Server_Static
+
+HA_Configurable_Server_Static_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+HA_Configurable_Server_Static_SOURCES = \
+ HA_Configurable_Server_Static.cpp \
+ HA_Status_Static.cpp \
+ HA_Status_Static.h
+
+HA_Configurable_Server_Static_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+endif !BUILD_ACE_FOR_TAO
+
+## Makefile.Svc_Config_HA_Status.am
+
+if !BUILD_ACE_FOR_TAO
+
+noinst_LTLIBRARIES = libHA_Status.la
+
+libHA_Status_la_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR) \
+ -DHASTATUS_BUILD_DLL
+
+libHA_Status_la_SOURCES = \
+ HA_Status_Dynamic.cpp
+
+noinst_HEADERS = \
+ HA_Status_Dynamic.h
+
+endif !BUILD_ACE_FOR_TAO
+
+## Clean up template repositories, etc.
+clean-local:
+ -rm -f *~ *.bak *.rpo *.sym lib*.*_pure_* core core.*
+ -rm -f gcctemp.c gcctemp so_locations *.ics
+ -rm -rf cxx_repository ptrepository ti_files
+ -rm -rf templateregistry ir.out
+ -rm -rf ptrepository SunWS_cache Templates.DB
diff --git a/ACE/examples/APG/Svc_Config/status.ini b/ACE/examples/APG/Svc_Config/status.ini
new file mode 100644
index 00000000000..8a36fb124fa
--- /dev/null
+++ b/ACE/examples/APG/Svc_Config/status.ini
@@ -0,0 +1,2 @@
+[HAStatus]
+"ListenPort"=dword:000001ec
diff --git a/ACE/examples/APG/Svc_Config/svc.conf.dynamic b/ACE/examples/APG/Svc_Config/svc.conf.dynamic
new file mode 100644
index 00000000000..e8ffb12c8ad
--- /dev/null
+++ b/ACE/examples/APG/Svc_Config/svc.conf.dynamic
@@ -0,0 +1,2 @@
+dynamic HA_Status_Dynamic_Service Service_Object *
+HA_Status:_make_HA_Status() "-f status.ini"
diff --git a/ACE/examples/APG/Svc_Config/svc.conf.static b/ACE/examples/APG/Svc_Config/svc.conf.static
new file mode 100644
index 00000000000..0103380c776
--- /dev/null
+++ b/ACE/examples/APG/Svc_Config/svc.conf.static
@@ -0,0 +1 @@
+static HA_Status_Static_Service "-f status.ini"
diff --git a/ACE/examples/APG/Svc_Config/svc_config.mpc b/ACE/examples/APG/Svc_Config/svc_config.mpc
new file mode 100644
index 00000000000..ddc33b97c53
--- /dev/null
+++ b/ACE/examples/APG/Svc_Config/svc_config.mpc
@@ -0,0 +1,28 @@
+// -*- MPC -*-
+// $Id$
+
+project(*HA Status) : acelib {
+ avoids += ace_for_tao
+ sharedname = HA_Status
+ dynamicflags = HASTATUS_BUILD_DLL
+ Source_Files {
+ HA_Status_Dynamic.cpp
+ }
+}
+
+project(HA Configurable Server Dynamic) : aceexe {
+ avoids += ace_for_tao
+ exename = HA_Configurable_Server_Dynamic
+ Source_Files {
+ HA_Configurable_Server_Dynamic.cpp
+ }
+}
+
+project(HA Configurable Server Static) : aceexe {
+ avoids += ace_for_tao
+ exename = HA_Configurable_Server_Static
+ Source_Files {
+ HA_Configurable_Server_Static.cpp
+ HA_Status_Static.cpp
+ }
+}
diff --git a/ACE/examples/APG/ThreadManagement/.cvsignore b/ACE/examples/APG/ThreadManagement/.cvsignore
new file mode 100644
index 00000000000..535a0039a50
--- /dev/null
+++ b/ACE/examples/APG/ThreadManagement/.cvsignore
@@ -0,0 +1,18 @@
+Async_Cancel
+Async_Cancel
+Coop_Cancel
+Coop_Cancel
+ExitHandler
+ExitHandler
+Pool
+Pool
+Priorities
+Priorities
+Signals
+Signals
+Signals2
+Signals2
+Start_Hook
+Start_Hook
+State
+State
diff --git a/ACE/examples/APG/ThreadManagement/Async_Cancel.cpp b/ACE/examples/APG/ThreadManagement/Async_Cancel.cpp
new file mode 100644
index 00000000000..5d5d5fcf0e8
--- /dev/null
+++ b/ACE/examples/APG/ThreadManagement/Async_Cancel.cpp
@@ -0,0 +1,63 @@
+// $Id$
+
+#include "ace/OS_NS_unistd.h"
+#include "ace/Task.h"
+#include "ace/Log_Msg.h"
+
+#if defined (ACE_HAS_PTHREADS)
+// Only works on Pthreads...
+
+// Listing 1 code/ch13
+class CanceledTask : public ACE_Task<ACE_MT_SYNCH>
+{
+public:
+ virtual int svc (void)
+ {
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("(%t) Starting thread\n")));
+
+ if (this->set_cancel_mode () < 0)
+ return -1;
+
+ while (1)
+ {
+ // Put this thread in a compute loop.. no
+ // cancellation points are available.
+ }
+ }
+
+ int set_cancel_mode (void)
+ {
+ cancel_state new_state;
+
+ // Set the cancel state to asynchronous and enabled.
+ new_state.cancelstate = PTHREAD_CANCEL_ENABLE;
+ new_state.canceltype = PTHREAD_CANCEL_ASYNCHRONOUS;
+ if (ACE_Thread::setcancelstate (new_state, 0) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("cancelstate")), -1);
+ return 0;
+ }
+};
+// Listing 1
+// Listing 2 code/ch13
+int ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ CanceledTask task;
+ task.activate ();
+ ACE_OS::sleep (1);
+ ACE_Thread_Manager::instance ()->cancel_task (&task, 1);
+ task.wait ();
+
+ return 0;
+}
+// Listing 2
+
+#else /* ACE_HAS_PTHREADS */
+int ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ puts ("This example works on Pthreads platforms.\n");
+ return 0;
+}
+#endif /* ACE_HAS_PTHREADS */
+
diff --git a/ACE/examples/APG/ThreadManagement/Coop_Cancel.cpp b/ACE/examples/APG/ThreadManagement/Coop_Cancel.cpp
new file mode 100644
index 00000000000..4a7714cf14b
--- /dev/null
+++ b/ACE/examples/APG/ThreadManagement/Coop_Cancel.cpp
@@ -0,0 +1,68 @@
+// $Id$
+
+#include "ace/config-lite.h"
+#if defined (ACE_HAS_THREADS)
+
+#include "ace/OS_NS_time.h"
+#include "ace/OS_NS_unistd.h"
+#include "ace/Task.h"
+#include "ace/Log_Msg.h"
+
+// Listing 1 code/ch13
+class CanceledTask : public ACE_Task<ACE_MT_SYNCH>
+{
+public:
+
+ virtual int svc (void)
+ {
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("(%t) starting up \n")));
+
+ // Cache our ACE_Thread_Manager pointer.
+ ACE_Thread_Manager *mgr = this->thr_mgr ();
+ while (1)
+ {
+ if (mgr->testcancel (mgr->thr_self ()))
+ return 0;
+
+ ACE_Message_Block *mb = 0;
+ ACE_Time_Value tv (0, 1000);
+ tv += ACE_OS::time (0);
+ int result = this->getq (mb, &tv);
+ if (result == -1 && errno == EWOULDBLOCK)
+ continue;
+ else
+ {
+ // Do real work.
+ }
+ }
+
+ ACE_NOTREACHED (return 0);
+ }
+};
+// Listing 1
+
+// Listing 2 code/ch13
+int ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ CanceledTask task;
+ task.activate ();
+
+ ACE_OS::sleep (1);
+
+ ACE_Thread_Manager::instance ()->cancel_task (&task);
+ task.wait ();
+ return 0;
+}
+// Listing 2
+
+#else
+#include "ace/OS_main.h"
+#include "ace/OS_NS_stdio.h"
+
+int ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ ACE_OS::puts (ACE_TEXT ("This example requires threads."));
+ return 0;
+}
+
+#endif /* ACE_HAS_THREADS */
diff --git a/ACE/examples/APG/ThreadManagement/ExitHandler.cpp b/ACE/examples/APG/ThreadManagement/ExitHandler.cpp
new file mode 100644
index 00000000000..85238eac052
--- /dev/null
+++ b/ACE/examples/APG/ThreadManagement/ExitHandler.cpp
@@ -0,0 +1,71 @@
+// $Id$
+
+// Listing 1 code/ch13
+#include "ace/Task.h"
+#include "ace/Log_Msg.h"
+
+class ExitHandler : public ACE_At_Thread_Exit
+{
+public:
+ virtual void apply (void)
+ {
+ ACE_DEBUG ((LM_INFO, ACE_TEXT ("(%t) is exiting \n")));
+
+ // Shut down all devices.
+ }
+};
+// Listing 1
+// Listing 2 code/ch13
+class HA_CommandHandler : public ACE_Task_Base
+{
+public:
+ HA_CommandHandler(ExitHandler& eh) : eh_(eh)
+ { }
+
+ virtual int svc (void)
+ {
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("(%t) starting up \n")));
+
+ this->thr_mgr ()->at_exit (eh_);
+
+ // Do something.
+
+ // Forcefully exit.
+ ACE_Thread::exit ();
+
+ // NOT REACHED
+ return 0;
+ }
+
+private:
+ ExitHandler& eh_;
+};
+// Listing 2
+// Listing 3 code/ch13
+int ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ ExitHandler eh;
+
+ HA_CommandHandler handler (eh);
+ handler.activate ();
+
+ ACE_Thread_Manager::instance ()->wait ();
+ return 0;
+}
+// Listing 3
+#if 0
+// Listing 4 code/ch13
+int ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ ExitHandler eh;
+ ACE_Thread_Manager tm;
+
+ HA_CommandHandler handler (eh);
+ handler.thr_mgr (&tm);
+ handler.activate ();
+
+ tm.wait();
+ return 0;
+}
+// Listing 4
+#endif
diff --git a/ACE/examples/APG/ThreadManagement/Makefile.am b/ACE/examples/APG/ThreadManagement/Makefile.am
new file mode 100644
index 00000000000..0ed91996db2
--- /dev/null
+++ b/ACE/examples/APG/ThreadManagement/Makefile.am
@@ -0,0 +1,146 @@
+## Process this file with automake to create Makefile.in
+##
+## $Id$
+##
+## This file was generated by MPC. Any changes made directly to
+## this file will be lost the next time it is generated.
+##
+## MPC Command:
+## /acebuilds/ACE_wrappers-repository/bin/mwc.pl -include /acebuilds/MPC/config -include /acebuilds/MPC/templates -feature_file /acebuilds/ACE_wrappers-repository/local.features -noreldefs -type automake -exclude build,Kokyu
+
+ACE_BUILDDIR = $(top_builddir)
+ACE_ROOT = $(top_srcdir)
+
+## Makefile.Async_Cancel.am
+noinst_PROGRAMS = Async_Cancel
+
+Async_Cancel_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+Async_Cancel_SOURCES = \
+ Async_Cancel.cpp \
+ SecurityContext.h
+
+Async_Cancel_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Makefile.Coop_Cancel.am
+noinst_PROGRAMS += Coop_Cancel
+
+Coop_Cancel_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+Coop_Cancel_SOURCES = \
+ Coop_Cancel.cpp \
+ SecurityContext.h
+
+Coop_Cancel_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Makefile.ExitHandler.am
+noinst_PROGRAMS += ExitHandler
+
+ExitHandler_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+ExitHandler_SOURCES = \
+ ExitHandler.cpp \
+ SecurityContext.h
+
+ExitHandler_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Makefile.Pool.am
+noinst_PROGRAMS += Pool
+
+Pool_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+Pool_SOURCES = \
+ Pool.cpp \
+ SecurityContext.h
+
+Pool_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Makefile.Priorities.am
+noinst_PROGRAMS += Priorities
+
+Priorities_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+Priorities_SOURCES = \
+ Priorities.cpp \
+ SecurityContext.h
+
+Priorities_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Makefile.Signals.am
+noinst_PROGRAMS += Signals
+
+Signals_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+Signals_SOURCES = \
+ Signals.cpp \
+ SecurityContext.h
+
+Signals_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Makefile.Signals2.am
+noinst_PROGRAMS += Signals2
+
+Signals2_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+Signals2_SOURCES = \
+ Signals2.cpp \
+ SecurityContext.h
+
+Signals2_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Makefile.Start_Hook.am
+noinst_PROGRAMS += Start_Hook
+
+Start_Hook_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+Start_Hook_SOURCES = \
+ Start_Hook.cpp \
+ SecurityContext.h
+
+Start_Hook_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Makefile.State.am
+noinst_PROGRAMS += State
+
+State_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+State_SOURCES = \
+ State.cpp \
+ SecurityContext.h
+
+State_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Clean up template repositories, etc.
+clean-local:
+ -rm -f *~ *.bak *.rpo *.sym lib*.*_pure_* core core.*
+ -rm -f gcctemp.c gcctemp so_locations *.ics
+ -rm -rf cxx_repository ptrepository ti_files
+ -rm -rf templateregistry ir.out
+ -rm -rf ptrepository SunWS_cache Templates.DB
diff --git a/ACE/examples/APG/ThreadManagement/Pool.cpp b/ACE/examples/APG/ThreadManagement/Pool.cpp
new file mode 100644
index 00000000000..30ae56801a5
--- /dev/null
+++ b/ACE/examples/APG/ThreadManagement/Pool.cpp
@@ -0,0 +1,46 @@
+// $Id$
+
+#include "ace/config-lite.h"
+#if defined (ACE_HAS_THREADS)
+
+#include "ace/Task.h"
+#include "ace/Log_Msg.h"
+
+// Listing 1 code/ch13
+class HA_CommandHandler : public ACE_Task<ACE_MT_SYNCH>
+{
+public:
+ virtual int svc (void)
+ {
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("(%t) starting up \n")));
+ ACE_Message_Block *mb;
+ if (this->getq (mb) == -1)
+ return -1;
+ // ... do something with the message.
+ return 0;
+ }
+};
+// Listing 1
+// Listing 2 code/ch13
+int ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ HA_CommandHandler handler;
+
+ // Create 4 threads.
+ handler.activate (THR_NEW_LWP | THR_JOINABLE, 4);
+ handler.wait ();
+ return 0;
+}
+// Listing 2
+
+#else
+#include "ace/OS_main.h"
+#include "ace/OS_NS_stdio.h"
+
+int ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ ACE_OS::puts (ACE_TEXT ("This example requires threads."));
+ return 0;
+}
+
+#endif /* ACE_HAS_THREADS */
diff --git a/ACE/examples/APG/ThreadManagement/Priorities.cpp b/ACE/examples/APG/ThreadManagement/Priorities.cpp
new file mode 100644
index 00000000000..3a80a613714
--- /dev/null
+++ b/ACE/examples/APG/ThreadManagement/Priorities.cpp
@@ -0,0 +1,104 @@
+// $Id$
+
+#include "ace/config-lite.h"
+
+#if defined (ACE_HAS_THREADS)
+
+#include "ace/Task.h"
+#include "ace/Log_Msg.h"
+#include "ace/OS_NS_unistd.h"
+
+// Listing 2 code/ch13
+class HA_CommandHandler : public ACE_Task<ACE_MT_SYNCH>
+{
+public:
+ HA_CommandHandler (const char *name) : name_ (name)
+ { }
+
+ virtual int svc (void)
+ {
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("(%t) starting up %C\n"),
+ name_));
+
+ ACE_OS::sleep (2);
+ ACE_Message_Block *mb = 0;
+ while (this->getq (mb) != -1)
+ {
+ if (mb->msg_type () == ACE_Message_Block::MB_BREAK)
+ {
+ mb->release ();
+ break;
+ }
+ process_message (mb);
+ mb->release ();
+ }
+ return 0;
+ }
+
+ void process_message (ACE_Message_Block *)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("(%t) Processing message %C\n"),
+ name_));
+ // Simulate compute bound task.
+ for (int i = 0; i < 100; i++)
+ ;
+ }
+
+private:
+ const char *name_;
+};
+// Listing 2
+
+#if !defined (ACE_THR_PRI_OTHER_MAX)
+// This should be fixed in ACE... There's no _MAX, _MIN values for
+// thread priorities.
+#if defined (ACE_WIN32)
+# define ACE_THR_PRI_OTHER_MAX ((ACE_THR_PRI_OTHER_DEF) + 1)
+#elif defined (VXWORKS)
+# define ACE_THR_PRI_OTHER_MAX 0
+#endif
+#endif
+
+// Listing 1 code/ch13
+int ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ HA_CommandHandler hp_handler ("HighPriority");
+ hp_handler.activate (THR_NEW_LWP | THR_JOINABLE,
+ 1, 1, ACE_THR_PRI_OTHER_MAX);
+
+ HA_CommandHandler lp_handler ("LowPriority");
+ lp_handler.activate (THR_NEW_LWP | THR_JOINABLE,
+ 1, 1, ACE_THR_PRI_OTHER_DEF);
+
+ ACE_Message_Block mb;
+ for (int i = 0; i < 100; i++)
+ {
+ ACE_Message_Block *mb_hp, *mb_lp;
+ mb_hp = mb.clone ();
+ mb_lp = mb.clone ();
+ hp_handler.putq (mb_hp);
+ lp_handler.putq (mb_lp);
+ }
+
+ ACE_Message_Block stop (0, ACE_Message_Block::MB_BREAK);
+ hp_handler.putq (stop.clone ());
+ lp_handler.putq (stop.clone ());
+ hp_handler.wait ();
+ lp_handler.wait ();
+
+ return 0;
+}
+// Listing 1
+
+#else
+#include "ace/OS_main.h"
+#include "ace/OS_NS_stdio.h"
+
+int ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ ACE_OS::puts (ACE_TEXT ("This example requires threads."));
+ return 0;
+}
+
+#endif /* ACE_HAS_THREADS */
diff --git a/ACE/examples/APG/ThreadManagement/SecurityContext.h b/ACE/examples/APG/ThreadManagement/SecurityContext.h
new file mode 100644
index 00000000000..73adbd1a435
--- /dev/null
+++ b/ACE/examples/APG/ThreadManagement/SecurityContext.h
@@ -0,0 +1,16 @@
+/**
+ * $Id$
+ *
+ * Sample code from The ACE Programmer's Guide,
+ * copyright 2003 Addison-Wesley. All Rights Reserved.
+ */
+
+#ifndef __SECURITYCONTEXT_H_
+#define __SECURITYCONTEXT_H_
+
+struct SecurityContext
+ {
+ const char * user;
+ };
+
+#endif /* __SECURITYCONTEXT_H_ */
diff --git a/ACE/examples/APG/ThreadManagement/Signals.cpp b/ACE/examples/APG/ThreadManagement/Signals.cpp
new file mode 100644
index 00000000000..85547ed3249
--- /dev/null
+++ b/ACE/examples/APG/ThreadManagement/Signals.cpp
@@ -0,0 +1,93 @@
+// $Id$
+
+#include "ace/config-lite.h"
+#if defined (ACE_HAS_THREADS)
+
+#include "ace/OS_NS_time.h"
+#include "ace/OS_NS_unistd.h"
+#include "ace/Task.h"
+#include "ace/Log_Msg.h"
+#include "ace/Signal.h"
+#include "ace/Sig_Handler.h"
+
+// Listing 1 code/ch13
+class SignalableTask : public ACE_Task<ACE_MT_SYNCH>
+{
+public:
+ virtual int handle_signal (int signum,
+ siginfo_t * = 0,
+ ucontext_t * = 0)
+ {
+ if (signum == SIGUSR1)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("(%t) received a %S signal\n"),
+ signum));
+ handle_alert ();
+ }
+ return 0;
+ }
+
+ virtual int svc (void)
+ {
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("(%t) Starting thread\n")));
+
+ while (1)
+ {
+ ACE_Message_Block* mb = 0;
+ ACE_Time_Value tv (0, 1000);
+ tv += ACE_OS::time (0);
+ int result = this->getq (mb, &tv);
+ if (result == -1 && errno == EWOULDBLOCK)
+ continue;
+ else
+ process_message (mb);
+ }
+
+ ACE_NOTREACHED (return 0);
+ }
+
+ void handle_alert ();
+ void process_message (ACE_Message_Block *mb);
+};
+// Listing 1
+
+void
+SignalableTask::process_message (ACE_Message_Block *)
+{
+}
+
+void
+SignalableTask::handle_alert ()
+{
+}
+
+// Listing 2 code/ch13
+int ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ SignalableTask handler;
+ handler.activate (THR_NEW_LWP | THR_JOINABLE , 5);
+
+ ACE_Sig_Handler sh;
+ sh.register_handler (SIGUSR1, &handler);
+
+ ACE_OS::sleep (1);
+
+ ACE_Thread_Manager::instance () ->
+ kill_grp (handler.grp_id (), SIGUSR1);
+ handler.wait ();
+ return 0;
+}
+// Listing 2
+
+#else
+#include "ace/OS_main.h"
+#include "ace/OS_NS_stdio.h"
+
+int ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ ACE_OS::puts (ACE_TEXT ("This example requires threads."));
+ return 0;
+}
+
+#endif /* ACE_HAS_THREADS */
diff --git a/ACE/examples/APG/ThreadManagement/Signals2.cpp b/ACE/examples/APG/ThreadManagement/Signals2.cpp
new file mode 100644
index 00000000000..0df855c45bb
--- /dev/null
+++ b/ACE/examples/APG/ThreadManagement/Signals2.cpp
@@ -0,0 +1,97 @@
+// $Id$
+
+#include "ace/config-lite.h"
+#if defined (ACE_HAS_THREADS)
+
+#include "ace/OS_NS_time.h"
+#include "ace/OS_NS_unistd.h"
+#include "ace/Task.h"
+#include "ace/Log_Msg.h"
+#include "ace/Signal.h"
+#include "ace/Sig_Handler.h"
+
+class SignalableTask : public ACE_Task<ACE_MT_SYNCH>
+{
+public:
+ virtual int handle_signal (int signum,
+ siginfo_t * = 0,
+ ucontext_t * = 0)
+ {
+ if (signum == SIGUSR1)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("(%t) received a %S signal\n"),
+ signum));
+ handle_alert();
+ }
+
+ return 0;
+ }
+
+ virtual int svc (void)
+ {
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("(%t) Starting thread\n")));
+
+ while (1)
+ {
+ ACE_Message_Block* mb = 0;
+ ACE_Time_Value tv (0, 1000);
+ tv += ACE_OS::time (0);
+
+ int result = this->getq(mb, &tv);
+
+ if (result == -1 && errno == EWOULDBLOCK)
+ continue;
+ else
+ process_message (mb);
+ }
+
+ ACE_NOTREACHED (return 0);
+ }
+
+ void handle_alert ();
+ void process_message (ACE_Message_Block *mb);
+};
+
+void
+SignalableTask::process_message (ACE_Message_Block *)
+{
+ return;
+}
+
+void
+SignalableTask::handle_alert (void)
+{
+ return;
+}
+
+// Listing 1 code/ch13
+int ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("(%t) Main thread \n")));
+ SignalableTask handler;
+ handler.activate (THR_NEW_LWP | THR_JOINABLE, 5);
+
+ ACE_Sig_Handler sh;
+ sh.register_handler (SIGUSR1, &handler);
+
+ ACE_OS::sleep (1); // Allow threads to start
+
+ for (int i = 0; i < 5; i++)
+ ACE_OS::kill (ACE_OS::getpid (), SIGUSR1);
+ handler.wait ();
+ return 0;
+}
+// Listing 1
+
+#else
+#include "ace/OS_main.h"
+#include "ace/OS_NS_stdio.h"
+
+int ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ ACE_OS::puts (ACE_TEXT ("This example requires threads."));
+ return 0;
+}
+
+#endif /* ACE_HAS_THREADS */
diff --git a/ACE/examples/APG/ThreadManagement/Start_Hook.cpp b/ACE/examples/APG/ThreadManagement/Start_Hook.cpp
new file mode 100644
index 00000000000..1c4ad0794b7
--- /dev/null
+++ b/ACE/examples/APG/ThreadManagement/Start_Hook.cpp
@@ -0,0 +1,60 @@
+// $Id$
+
+#include "ace/Thread_Hook.h"
+#include "ace/Task.h"
+#include "ace/Log_Msg.h"
+
+#include "SecurityContext.h"
+
+// Listing 1 code/ch13
+class HA_ThreadHook : public ACE_Thread_Hook
+{
+public:
+ virtual ACE_THR_FUNC_RETURN start (ACE_THR_FUNC func, void* arg)
+ {
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT("(%t) New Thread Spawned\n")));
+
+ // Create the context on the thread's own stack.
+ ACE_TSS<SecurityContext> secCtx;
+ // Special initialization.
+ add_sec_context_thr (secCtx);
+
+ return (*func) (arg);
+ }
+
+ void add_sec_context_thr (ACE_TSS<SecurityContext> &secCtx);
+};
+// Listing 1
+
+void
+HA_ThreadHook::add_sec_context_thr(ACE_TSS<SecurityContext> &secCtx)
+{
+ secCtx->user = 0;
+}
+
+
+class HA_CommandHandler : public ACE_Task_Base
+{
+public:
+ virtual int svc (void)
+ {
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("(%t) starting up \n")));
+
+ // Do something.
+
+ return 0;
+ }
+};
+// Listing 2 code/ch13
+int ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ HA_ThreadHook hook;
+ ACE_Thread_Hook::thread_hook (&hook);
+
+ HA_CommandHandler handler;
+ handler.activate ();
+ handler.wait();
+ return 0;
+}
+// Listing 2
+
diff --git a/ACE/examples/APG/ThreadManagement/State.cpp b/ACE/examples/APG/ThreadManagement/State.cpp
new file mode 100644
index 00000000000..d95433440c7
--- /dev/null
+++ b/ACE/examples/APG/ThreadManagement/State.cpp
@@ -0,0 +1,39 @@
+// $Id$
+
+#include "ace/Task.h"
+
+class HA_CommandHandler : public ACE_Task_Base
+{
+public:
+ virtual int svc (void)
+ {
+ ACE_DEBUG
+ ((LM_DEBUG, ACE_TEXT ("(%t) Handler Thread running\n")));
+ return 0;
+ }
+};
+
+
+int ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("(%t) Main Thread running\n")));
+// Listing 1 code/ch13
+ HA_CommandHandler handler;
+ int result = handler.activate (THR_NEW_LWP |
+ THR_JOINABLE |
+ THR_SUSPENDED);
+ ACE_ASSERT (result == 0);
+
+ ACE_UNUSED_ARG (result);
+
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("(%t) The current thread count is %d\n"),
+ handler.thr_count ()));
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("(%t) The group identifier is %d\n"),
+ handler.grp_id ()));
+ handler.resume ();
+ handler.wait ();
+// Listing 1
+ return 0;
+}
diff --git a/ACE/examples/APG/ThreadManagement/threadmgmt.mpc b/ACE/examples/APG/ThreadManagement/threadmgmt.mpc
new file mode 100644
index 00000000000..bb765150abb
--- /dev/null
+++ b/ACE/examples/APG/ThreadManagement/threadmgmt.mpc
@@ -0,0 +1,65 @@
+// -*- MPC -*-
+// $Id$
+
+project(Async Cancel) : aceexe {
+ exename = Async_Cancel
+ Source_Files {
+ Async_Cancel.cpp
+ }
+}
+
+project(Coop Cancel) : aceexe {
+ exename = Coop_Cancel
+ Source_Files {
+ Coop_Cancel.cpp
+ }
+}
+
+project(ExitHandler) : aceexe {
+ exename = ExitHandler
+ Source_Files {
+ ExitHandler.cpp
+ }
+}
+
+project(Pool) : aceexe {
+ exename = Pool
+ Source_Files {
+ Pool.cpp
+ }
+}
+
+project(Priorities) : aceexe {
+ exename = Priorities
+ Source_Files {
+ Priorities.cpp
+ }
+}
+
+project(Signals) : aceexe {
+ exename = Signals
+ Source_Files {
+ Signals.cpp
+ }
+}
+
+project(Signals2) : aceexe {
+ exename = Signals2
+ Source_Files {
+ Signals2.cpp
+ }
+}
+
+project(Start Hook) : aceexe {
+ exename = Start_Hook
+ Source_Files {
+ Start_Hook.cpp
+ }
+}
+
+project(State) : aceexe {
+ exename = State
+ Source_Files {
+ State.cpp
+ }
+}
diff --git a/ACE/examples/APG/ThreadPools/.cvsignore b/ACE/examples/APG/ThreadPools/.cvsignore
new file mode 100644
index 00000000000..7052a85815f
--- /dev/null
+++ b/ACE/examples/APG/ThreadPools/.cvsignore
@@ -0,0 +1,10 @@
+Futures
+Futures
+LF_ThreadPool
+LF_ThreadPool
+TP_Reactor
+TP_Reactor
+Task_ThreadPool
+Task_ThreadPool
+ThreadPool
+ThreadPool
diff --git a/ACE/examples/APG/ThreadPools/Futures.cpp b/ACE/examples/APG/ThreadPools/Futures.cpp
new file mode 100644
index 00000000000..361a8bb43a2
--- /dev/null
+++ b/ACE/examples/APG/ThreadPools/Futures.cpp
@@ -0,0 +1,321 @@
+// $Id$
+
+#include "ace/config-lite.h"
+#if defined (ACE_HAS_THREADS)
+
+#include "ace/OS_NS_string.h"
+#include "ace/OS_NS_time.h"
+#include "ace/Task.h"
+#include "ace/Unbounded_Queue.h"
+#include "ace/Synch.h"
+#include "ace/SString.h"
+#include "ace/Method_Request.h"
+#include "ace/Future.h"
+#include "ace/Activation_Queue.h"
+
+#define OUTSTANDING_REQUESTS 20
+
+// Listing 2 code/ch16
+class CompletionCallBack: public ACE_Future_Observer<ACE_CString*>
+{
+public:
+ virtual void update (const ACE_Future<ACE_CString*> & future)
+ {
+ ACE_CString *result = 0;
+
+ // Block for the result.
+ future.get (result);
+ ACE_DEBUG ((LM_INFO, ACE_TEXT("%C\n"), result->c_str ()));
+ delete result;
+ }
+};
+// Listing 2
+// Listing 1 code/ch16
+class LongWork : public ACE_Method_Request
+{
+public:
+ virtual int call (void)
+ {
+ ACE_TRACE (ACE_TEXT ("LongWork::call"));
+ ACE_DEBUG
+ ((LM_INFO, ACE_TEXT ("(%t) Attempting long work task\n")));
+ ACE_OS::sleep (1);
+
+ char buf[1024];
+ ACE_OS::strcpy (buf, "Completed assigned task\n");
+ ACE_CString *msg;
+ ACE_NEW_RETURN
+ (msg, ACE_CString (buf, ACE_OS::strlen (buf) + 1), -1);
+ result_.set (msg);
+ return 0;
+ }
+
+ ACE_Future<ACE_CString*> &future (void)
+ {
+ ACE_TRACE (ACE_TEXT ("LongWork::future"));
+ return result_;
+ }
+
+ void attach (CompletionCallBack *cb)
+ {
+ result_.attach (cb);
+ }
+
+private:
+ ACE_Future<ACE_CString*> result_;
+};
+// Listing 1
+
+class Exit : public ACE_Method_Request
+{
+public:
+ virtual int call (void)
+ {
+ ACE_TRACE (ACE_TEXT ("Exit::call"));
+ return -1;
+ }
+};
+
+class Worker;
+
+class IManager
+{
+public:
+ virtual ~IManager (void) { }
+
+ virtual int return_to_work (Worker *worker) = 0;
+};
+
+// Listing 3 code/ch16
+class Worker: public ACE_Task<ACE_MT_SYNCH>
+{
+public:
+ Worker (IManager *manager)
+ : manager_(manager), queue_ (msg_queue ())
+ { }
+
+ int perform (ACE_Method_Request *req)
+ {
+ ACE_TRACE (ACE_TEXT ("Worker::perform"));
+ return this->queue_.enqueue (req);
+ }
+
+ virtual int svc (void)
+ {
+ thread_id_ = ACE_Thread::self ();
+ while (1)
+ {
+ ACE_Method_Request *request = this->queue_.dequeue();
+ if (request == 0)
+ return -1;
+
+ // Invoke the request
+ int result = request->call ();
+ if (result == -1)
+ break;
+
+ // Return to work.
+ this->manager_->return_to_work (this);
+ }
+
+ return 0;
+ }
+
+ ACE_thread_t thread_id (void);
+
+private:
+ IManager *manager_;
+ ACE_thread_t thread_id_;
+ ACE_Activation_Queue queue_;
+};
+// Listing 3
+
+ACE_thread_t Worker::thread_id (void)
+{
+ return thread_id_;
+}
+
+// Listing 4 code/ch16
+class Manager : public ACE_Task_Base, private IManager
+{
+public:
+ enum {POOL_SIZE = 5, MAX_TIMEOUT = 5};
+
+ Manager ()
+ : shutdown_(0), workers_lock_(), workers_cond_(workers_lock_)
+ {
+ ACE_TRACE (ACE_TEXT ("Manager::TP"));
+ }
+
+ int perform (ACE_Method_Request *req)
+ {
+ ACE_TRACE (ACE_TEXT ("Manager::perform"));
+ return this->queue_.enqueue (req);
+ }
+
+ int svc (void)
+ {
+ ACE_TRACE (ACE_TEXT ("Manager::svc"));
+
+ ACE_DEBUG ((LM_INFO, ACE_TEXT ("(%t) Manager started\n")));
+
+ // Create pool when you get in the first time.
+ create_worker_pool ();
+
+ while (!done ())
+ {
+ ACE_Time_Value tv ((long)MAX_TIMEOUT);
+ tv += ACE_OS::time (0);
+
+ // Get the next message
+ ACE_Method_Request *request = this->queue_.dequeue (&tv);
+ if (request == 0)
+ {
+ shut_down ();
+ break;
+ }
+
+ // Choose a worker.
+ Worker *worker = choose_worker ();
+
+ // Ask the worker to do the job.
+ worker->perform (request);
+ }
+
+ return 0;
+ }
+
+ int shut_down (void);
+
+ virtual int return_to_work (Worker *worker)
+ {
+ ACE_GUARD_RETURN
+ (ACE_Thread_Mutex, worker_mon, this->workers_lock_, -1);
+ ACE_DEBUG
+ ((LM_DEBUG, ACE_TEXT ("(%t) Worker returning to work.\n")));
+ this->workers_.enqueue_tail (worker);
+ this->workers_cond_.signal ();
+
+ return 0;
+ }
+
+private:
+ Worker *choose_worker (void)
+ {
+ ACE_GUARD_RETURN
+ (ACE_Thread_Mutex, worker_mon, this->workers_lock_, 0)
+
+ while (this->workers_.is_empty ())
+ workers_cond_.wait ();
+
+ Worker *worker = 0;
+ this->workers_.dequeue_head (worker);
+ return worker;
+ }
+
+ int create_worker_pool (void)
+ {
+ ACE_GUARD_RETURN
+ (ACE_Thread_Mutex, worker_mon, this->workers_lock_, -1);
+ for (int i = 0; i < POOL_SIZE; i++)
+ {
+ Worker *worker;
+ ACE_NEW_RETURN (worker, Worker (this), -1);
+ this->workers_.enqueue_tail (worker);
+ worker->activate ();
+ }
+
+ return 0;
+ }
+
+ int done (void)
+ {
+ return (shutdown_ == 1);
+ }
+
+ ACE_thread_t thread_id (Worker *worker)
+ {
+ return worker->thread_id ();
+ }
+
+private:
+ int shutdown_;
+ ACE_Thread_Mutex workers_lock_;
+ ACE_Condition<ACE_Thread_Mutex> workers_cond_;
+ ACE_Unbounded_Queue<Worker* > workers_;
+ ACE_Activation_Queue queue_;
+};
+// Listing 4
+
+int
+Manager::shut_down (void)
+{
+ ACE_TRACE (ACE_TEXT ("Manager::shut_down"));
+ ACE_Unbounded_Queue<Worker* >::ITERATOR iter = this->workers_.begin ();
+ Worker **worker_ptr = 0;
+ do
+ {
+ iter.next (worker_ptr);
+ Worker *worker = (*worker_ptr);
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("(%t) Attempting shutdown of %d\n"),
+ thread_id (worker)));
+
+ Exit *req;
+ ACE_NEW_RETURN (req, Exit(), -1);
+
+ // Send the hangup message
+ worker->perform (req);
+
+ // Wait for the exit.
+ worker->wait ();
+
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("(%t) Worker %d shut down.\n"),
+ thread_id (worker)));
+
+ delete req;
+ delete worker;
+
+ }
+ while (iter.advance ());
+
+ shutdown_ = 1;
+
+ return 0;
+}
+
+// Listing 5 code/ch16
+int ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ Manager tp;
+ tp.activate ();
+
+ ACE_Time_Value tv;
+ tv.msec (100);
+
+ // Wait for a few seconds every time you send a message.
+ CompletionCallBack cb;
+ LongWork workArray[OUTSTANDING_REQUESTS];
+ for (int i = 0; i < OUTSTANDING_REQUESTS; i++)
+ {
+ workArray[i].attach (&cb);
+ ACE_OS::sleep (tv);
+ tp.perform (&workArray[i]);
+ }
+
+ ACE_Thread_Manager::instance ()->wait ();
+ return 0;
+}
+// Listing 5
+
+#else
+#include "ace/OS_main.h"
+#include "ace/OS_NS_stdio.h"
+
+int ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ ACE_OS::puts (ACE_TEXT ("This example requires threads."));
+ return 0;
+}
+
+#endif /* ACE_HAS_THREADS */
diff --git a/ACE/examples/APG/ThreadPools/LF_ThreadPool.cpp b/ACE/examples/APG/ThreadPools/LF_ThreadPool.cpp
new file mode 100644
index 00000000000..820e74c36e8
--- /dev/null
+++ b/ACE/examples/APG/ThreadPools/LF_ThreadPool.cpp
@@ -0,0 +1,252 @@
+// $Id$
+
+#include "ace/config-lite.h"
+#if defined (ACE_HAS_THREADS)
+
+#include "ace/OS_NS_string.h"
+#include "ace/OS_NS_sys_time.h"
+#include "ace/Task.h"
+#include "ace/Containers.h"
+#include "ace/Synch.h"
+
+// Listing 4 code/ch16
+class Follower
+{
+public:
+ Follower (ACE_Thread_Mutex &leader_lock)
+ : cond_(leader_lock)
+ {
+ owner_ = ACE_Thread::self ();
+ }
+
+ int wait (void)
+ {
+ return this->cond_.wait ();
+ }
+
+ int signal (void)
+ {
+ return this->cond_.signal ();
+ }
+
+ ACE_thread_t owner (void)
+ {
+ return this->owner_;
+ }
+
+private:
+ ACE_Condition<ACE_Thread_Mutex> cond_;
+ ACE_thread_t owner_;
+};
+// Listing 4
+// Listing 1 code/ch16
+class LF_ThreadPool : public ACE_Task<ACE_MT_SYNCH>
+{
+public:
+ LF_ThreadPool () : shutdown_(0), current_leader_(0)
+ {
+ ACE_TRACE (ACE_TEXT ("LF_ThreadPool::TP"));
+ }
+
+ virtual int svc (void);
+
+ void shut_down (void)
+ {
+ shutdown_ = 1;
+ }
+
+private:
+ int become_leader (void);
+
+ Follower *make_follower (void);
+
+ int elect_new_leader (void);
+
+ int leader_active (void)
+ {
+ ACE_TRACE (ACE_TEXT ("LF_ThreadPool::leader_active"));
+ return this->current_leader_ != 0;
+ }
+
+ void leader_active (ACE_thread_t leader)
+ {
+ ACE_TRACE (ACE_TEXT ("LF_ThreadPool::leader_active"));
+ this->current_leader_ = leader;
+ }
+
+ void process_message (ACE_Message_Block *mb);
+
+ int done (void)
+ {
+ return (shutdown_ == 1);
+ }
+
+private:
+ int shutdown_;
+ ACE_thread_t current_leader_;
+ ACE_Thread_Mutex leader_lock_;
+ ACE_Unbounded_Queue<Follower*> followers_;
+ ACE_Thread_Mutex followers_lock_;
+ static long LONG_TIME;
+};
+// Listing 1
+// Listing 2 code/ch16
+int
+LF_ThreadPool::svc (void)
+{
+ ACE_TRACE (ACE_TEXT ("LF_ThreadPool::svc"));
+ while (!done ())
+ {
+ become_leader (); // Block until this thread is the leader.
+
+ ACE_Message_Block *mb = 0;
+ ACE_Time_Value tv (LONG_TIME);
+ tv += ACE_OS::gettimeofday ();
+
+ // Get a message, elect new leader, then process message.
+ if (this->getq (mb, &tv) < 0)
+ {
+ if (elect_new_leader () == 0)
+ break;
+ continue;
+ }
+
+ elect_new_leader ();
+ process_message (mb);
+ }
+
+ return 0;
+}
+// Listing 2
+// Listing 3 code/ch16
+int
+LF_ThreadPool::become_leader (void)
+{
+ ACE_TRACE (ACE_TEXT ("LF_ThreadPool::become_leader"));
+
+ ACE_GUARD_RETURN
+ (ACE_Thread_Mutex, leader_mon, this->leader_lock_, -1);
+ if (leader_active ())
+ {
+ Follower *fw = make_follower ();
+ {
+ // Wait until told to do so.
+ while (leader_active ())
+ fw->wait ();
+ }
+
+ delete fw;
+ }
+
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("(%t) Becoming the leader\n")));
+
+ // Mark yourself as the active leader.
+ leader_active (ACE_Thread::self ());
+ return 0;
+}
+
+Follower*
+LF_ThreadPool::make_follower (void)
+{
+ ACE_TRACE (ACE_TEXT ("LF_ThreadPool::make_follower"));
+
+ ACE_GUARD_RETURN
+ (ACE_Thread_Mutex, follower_mon, this->followers_lock_, 0);
+ Follower *fw;
+ ACE_NEW_RETURN (fw, Follower (this->leader_lock_), 0);
+ this->followers_.enqueue_tail (fw);
+ return fw;
+}
+// Listing 3
+// Listing 5 code/ch16
+int
+LF_ThreadPool::elect_new_leader (void)
+{
+ ACE_TRACE (ACE_TEXT ("LF_ThreadPool::elect_new_leader"));
+
+ ACE_GUARD_RETURN
+ (ACE_Thread_Mutex, leader_mon, this->leader_lock_, -1);
+ leader_active (0);
+
+ // Wake up a follower
+ if (!followers_.is_empty ())
+ {
+ ACE_GUARD_RETURN (ACE_Thread_Mutex,
+ follower_mon,
+ this->followers_lock_,
+ -1);
+ // Get the old follower.
+ Follower *fw;
+ if (this->followers_.dequeue_head (fw) != 0)
+ return -1;
+ ACE_DEBUG ((LM_ERROR,
+ ACE_TEXT ("(%t) Resigning and Electing %d\n"),
+ fw->owner ()));
+ return (fw->signal () == 0) ? 0 : -1;
+ }
+ else
+ {
+ ACE_DEBUG
+ ((LM_ERROR, ACE_TEXT ("(%t) Oops no followers left\n")));
+ return -1;
+ }
+}
+// Listing 5
+
+void
+LF_ThreadPool::process_message (ACE_Message_Block *mb)
+{
+ ACE_TRACE (ACE_TEXT ("LF_ThreadPool::process_message"));
+ int msgId;
+ ACE_OS::memcpy (&msgId, mb->rd_ptr (), sizeof(int));
+ mb->release ();
+
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("(%t) Started processing message:%d\n"),
+ msgId));
+ ACE_OS::sleep (1);
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("(%t) Finished processing message:%d\n"),
+ msgId));
+}
+
+long LF_ThreadPool::LONG_TIME = 5L;
+
+int ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ LF_ThreadPool tp;
+ tp.activate (THR_NEW_LWP| THR_JOINABLE, 5);
+
+ // Wait for a few seconds...
+ ACE_OS::sleep (2);
+ ACE_Time_Value tv (1L);
+
+ ACE_Message_Block *mb;
+ for (int i = 0; i < 30; i++)
+ {
+ ACE_NEW_RETURN (mb, ACE_Message_Block (sizeof(int)), -1);
+ ACE_OS::memcpy (mb->wr_ptr (), &i, sizeof(int));
+ ACE_OS::sleep (tv);
+
+ // Add a new work item.
+ tp.putq (mb);
+ }
+
+ ACE_Thread_Manager::instance ()->wait ();
+
+ ACE_OS::sleep (10);
+
+ return 0;
+}
+
+#else
+#include "ace/OS_main.h"
+#include "ace/OS_NS_stdio.h"
+
+int ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ ACE_OS::puts (ACE_TEXT ("This example requires threads."));
+ return 0;
+}
+
+#endif /* ACE_HAS_THREADS */
diff --git a/ACE/examples/APG/ThreadPools/Makefile.am b/ACE/examples/APG/ThreadPools/Makefile.am
new file mode 100644
index 00000000000..f1167e857c5
--- /dev/null
+++ b/ACE/examples/APG/ThreadPools/Makefile.am
@@ -0,0 +1,96 @@
+## Process this file with automake to create Makefile.in
+##
+## $Id$
+##
+## This file was generated by MPC. Any changes made directly to
+## this file will be lost the next time it is generated.
+##
+## MPC Command:
+## /acebuilds/ACE_wrappers-repository/bin/mwc.pl -include /acebuilds/MPC/config -include /acebuilds/MPC/templates -feature_file /acebuilds/ACE_wrappers-repository/local.features -noreldefs -type automake -exclude build,Kokyu
+
+ACE_BUILDDIR = $(top_builddir)
+ACE_ROOT = $(top_srcdir)
+
+noinst_PROGRAMS =
+
+## Makefile.Futures.am
+
+if !BUILD_ACE_FOR_TAO
+noinst_PROGRAMS += Futures
+
+Futures_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+Futures_SOURCES = \
+ Futures.cpp \
+ Request_Handler.h
+
+Futures_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+endif !BUILD_ACE_FOR_TAO
+
+## Makefile.LF_ThreadPool.am
+noinst_PROGRAMS += LF_ThreadPool
+
+LF_ThreadPool_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+LF_ThreadPool_SOURCES = \
+ LF_ThreadPool.cpp \
+ Request_Handler.h
+
+LF_ThreadPool_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Makefile.TP_Reactor.am
+noinst_PROGRAMS += TP_Reactor
+
+TP_Reactor_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+TP_Reactor_SOURCES = \
+ TP_Reactor.cpp \
+ Request_Handler.h
+
+TP_Reactor_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Makefile.Task_ThreadPool.am
+noinst_PROGRAMS += Task_ThreadPool
+
+Task_ThreadPool_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+Task_ThreadPool_SOURCES = \
+ Task_ThreadPool.cpp \
+ Request_Handler.h
+
+Task_ThreadPool_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Makefile.ThreadPool.am
+noinst_PROGRAMS += ThreadPool
+
+ThreadPool_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+ThreadPool_SOURCES = \
+ ThreadPool.cpp \
+ Request_Handler.h
+
+ThreadPool_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Clean up template repositories, etc.
+clean-local:
+ -rm -f *~ *.bak *.rpo *.sym lib*.*_pure_* core core.*
+ -rm -f gcctemp.c gcctemp so_locations *.ics
+ -rm -rf cxx_repository ptrepository ti_files
+ -rm -rf templateregistry ir.out
+ -rm -rf ptrepository SunWS_cache Templates.DB
diff --git a/ACE/examples/APG/ThreadPools/Request_Handler.h b/ACE/examples/APG/ThreadPools/Request_Handler.h
new file mode 100644
index 00000000000..9965fb7a30e
--- /dev/null
+++ b/ACE/examples/APG/ThreadPools/Request_Handler.h
@@ -0,0 +1,34 @@
+/**
+ * $Id$
+ *
+ * Sample code from The ACE Programmer's Guide,
+ * copyright 2003 Addison-Wesley. All Rights Reserved.
+ */
+
+#ifndef __REQUEST_HANDLER_H_
+#define __REQUEST_HANDLER_H_
+
+#include "ace/Svc_Handler.h"
+#include "ace/SOCK_Stream.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+class ACE_Thread_Manager;
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+class Request_Handler : public ACE_Svc_Handler<ACE_SOCK_STREAM, ACE_MT_SYNCH>
+ {
+ // = TITLE
+ // This class is the Svc_Handler used by <Acceptor>.
+ public:
+ Request_Handler (ACE_Thread_Manager *tm = 0);
+ // The default constructor makes sure the right reactor is used.
+
+ protected:
+ virtual int handle_input (ACE_HANDLE fd = ACE_INVALID_HANDLE);
+ virtual int handle_close (ACE_HANDLE fd, ACE_Reactor_Mask = 0);
+
+ private:
+ size_t nr_msgs_rcvd_;
+ };
+
+#endif /* __REQUEST_HANDLER_H_ */
diff --git a/ACE/examples/APG/ThreadPools/TP_Reactor.cpp b/ACE/examples/APG/ThreadPools/TP_Reactor.cpp
new file mode 100644
index 00000000000..9c82907a8e6
--- /dev/null
+++ b/ACE/examples/APG/ThreadPools/TP_Reactor.cpp
@@ -0,0 +1,269 @@
+// == == == == == == == == == == == == == == == == == == == == == == ==
+// $Id$
+// Stolen from $ACE_ROOT/tests/Thread_Pool_Reactor_Test.cpp
+// Thread_Pool_Reactor_Test.cpp, v 1.29 2001/03/20 01:07:21 irfan Exp
+// = AUTHOR
+// Irfan Pyarali <irfan@cs.wustl.edu> and
+// Nanbor Wang <nanbor@cs.wustl.edu>
+// == == == == == == == == == == == == == == == == == == == == == == ==
+
+#include "ace/config-lite.h"
+#if defined (ACE_HAS_THREADS)
+
+#include "ace/OS_NS_string.h"
+#include "ace/OS_NS_unistd.h"
+#include "ace/SOCK_Connector.h"
+#include "ace/SOCK_Acceptor.h"
+#include "ace/Acceptor.h"
+#include "ace/Thread_Manager.h"
+#include "ace/TP_Reactor.h"
+
+#include "Request_Handler.h"
+
+// Accepting end point. This is actually "localhost:10010", but some
+// platform couldn't resolve the name so we use the IP address
+// directly here.
+static const ACE_TCHAR *rendezvous = ACE_TEXT ("127.0.0.1:10010");
+
+// Total number of server threads.
+static size_t svr_thrno = 5;
+
+// Total number of client threads.
+static size_t cli_runs = 2;
+
+// Total connection attemps of a client thread.
+static size_t cli_conn_no = 2;
+
+// Total requests a client thread sends.
+static size_t cli_req_no = 5;
+
+// Delay before a thread sending the next request (in msec.)
+static int req_delay = 50;
+
+
+typedef ACE_Strategy_Acceptor <Request_Handler, ACE_SOCK_ACCEPTOR> ACCEPTOR;
+
+
+Request_Handler::Request_Handler (ACE_Thread_Manager *thr_mgr)
+ : ACE_Svc_Handler<ACE_SOCK_STREAM, ACE_MT_SYNCH> (thr_mgr),
+ nr_msgs_rcvd_(0)
+{
+ this->reactor (ACE_Reactor::instance ());
+}
+
+int
+Request_Handler::handle_input (ACE_HANDLE fd)
+{
+ ACE_TCHAR buffer[BUFSIZ];
+ ACE_TCHAR len = 0;
+ ssize_t result = this->peer ().recv (&len, sizeof (ACE_TCHAR));
+
+ if (result > 0
+ && this->peer ().recv_n (buffer, len * sizeof (ACE_TCHAR))
+ == static_cast<ssize_t> (len * sizeof (ACE_TCHAR)))
+ {
+ ++this->nr_msgs_rcvd_;
+
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("(%t) svr input; fd: 0x%x; input: %s\n"),
+ fd,
+ buffer));
+ if (ACE_OS::strcmp (buffer, ACE_TEXT ("shutdown")) == 0)
+ ACE_Reactor::instance()->end_reactor_event_loop ();
+ return 0;
+ }
+ else
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("(%t) Request_Handler: 0x%x peer closed (0x%x)\n"),
+ this, fd));
+ return -1;
+}
+
+int
+Request_Handler::handle_close (ACE_HANDLE fd, ACE_Reactor_Mask)
+{
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("(%t) svr close; fd: 0x%x, rcvd %d msgs\n"),
+ fd,
+ this->nr_msgs_rcvd_));
+
+ if (this->nr_msgs_rcvd_ != cli_req_no)
+ ACE_ERROR((LM_ERROR,
+ ACE_TEXT ("(%t) Handler 0x%x: Expected %d messages; got %d\n"),
+ this,
+ cli_req_no,
+ this->nr_msgs_rcvd_));
+
+ this->destroy ();
+ return 0;
+}
+
+// Listing 2 code/ch16
+static int
+reactor_event_hook (ACE_Reactor *)
+{
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("(%t) handling events ....\n")));
+
+ return 0;
+}
+
+class ServerTP : public ACE_Task_Base
+{
+public:
+ virtual int svc (void)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("(%t) Running the event loop\n")));
+
+ int result =
+ ACE_Reactor::instance ()->run_reactor_event_loop
+ (&reactor_event_hook);
+
+ if (result == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("(%t) %p\n"),
+ ACE_TEXT ("Error handling events")),
+ 0);
+
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("(%t) Done handling events.\n")));
+
+ return 0;
+ }
+};
+// Listing 2
+
+class Client: public ACE_Task_Base
+ {
+ public:
+ Client()
+ :addr_(rendezvous)
+ {}
+
+ virtual int svc()
+ {
+ ACE_OS::sleep (3);
+ const ACE_TCHAR *msg =
+ ACE_TEXT ("Message from Connection worker");
+
+ ACE_TCHAR buf [BUFSIZ];
+ buf[0] = ACE_OS::strlen (msg) + 1;
+ ACE_OS::strcpy (&buf[1], msg);
+
+ for (size_t i = 0; i < cli_runs; i++)
+ send_work_to_server(buf);
+
+ shut_down();
+
+ return 0;
+ }
+
+ private:
+ void send_work_to_server(ACE_TCHAR* arg)
+ {
+ ACE_SOCK_Stream stream;
+ ACE_SOCK_Connector connect;
+ ACE_Time_Value delay (0, req_delay);
+ size_t len = * reinterpret_cast<ACE_TCHAR *> (arg);
+
+ for (size_t i = 0 ; i < cli_conn_no; i++)
+ {
+ if (connect.connect (stream, addr_) < 0)
+ {
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("(%t) %p\n"),
+ ACE_TEXT ("connect")));
+ continue;
+ }
+
+ for (size_t j = 0; j < cli_req_no; j++)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("Sending work to server on handle 0x%x, req %d\n"),
+ stream.get_handle (),
+ j+1));
+ if (stream.send_n (arg,
+ (len + 1) * sizeof (ACE_TCHAR)) == -1)
+ {
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("(%t) %p\n"),
+ ACE_TEXT ("send_n")));
+ continue;
+ }
+ ACE_OS::sleep (delay);
+ }
+
+ stream.close ();
+ }
+
+ }
+
+ void shut_down()
+ {
+ ACE_SOCK_Stream stream;
+ ACE_SOCK_Connector connect;
+
+ if (connect.connect (stream, addr_) == -1)
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("(%t) %p Error while connecting\n"),
+ ACE_TEXT ("connect")));
+
+ const ACE_TCHAR *sbuf = ACE_TEXT ("\011shutdown");
+
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("shutdown stream handle = %x\n"),
+ stream.get_handle ()));
+
+ if (stream.send_n (sbuf, (ACE_OS::strlen (sbuf) + 1) * sizeof (ACE_TCHAR)) == -1)
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("(%t) %p\n"),
+ ACE_TEXT ("send_n")));
+
+ stream.close ();
+ }
+ private:
+ ACE_INET_Addr addr_;
+ };
+// Listing 1 code/ch16
+int ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ ACE_TP_Reactor sr;
+ ACE_Reactor new_reactor (&sr);
+ ACE_Reactor::instance (&new_reactor);
+
+ ACCEPTOR acceptor;
+ ACE_INET_Addr accept_addr (rendezvous);
+
+ if (acceptor.open (accept_addr) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("open")),
+ 1);
+
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("(%t) Spawning %d server threads...\n"),
+ svr_thrno));
+
+ ServerTP serverTP;
+ serverTP.activate (THR_NEW_LWP | THR_JOINABLE, svr_thrno);
+
+ Client client;
+ client.activate ();
+
+ ACE_Thread_Manager::instance ()->wait ();
+
+ return 0;
+}
+// Listing 1
+#else
+#include "ace/OS_main.h"
+#include "ace/OS_NS_stdio.h"
+
+int ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ ACE_OS::puts (ACE_TEXT ("This example requires threads."));
+ return 0;
+}
+
+#endif /* ACE_HAS_THREADS */
diff --git a/ACE/examples/APG/ThreadPools/Task_ThreadPool.cpp b/ACE/examples/APG/ThreadPools/Task_ThreadPool.cpp
new file mode 100644
index 00000000000..53ebe76b0bc
--- /dev/null
+++ b/ACE/examples/APG/ThreadPools/Task_ThreadPool.cpp
@@ -0,0 +1,149 @@
+// $Id$
+
+#include "ace/config-lite.h"
+#if defined (ACE_HAS_THREADS)
+
+#include "ace/OS_NS_string.h"
+#include "ace/OS_NS_time.h"
+#include "ace/Task.h"
+#include "ace/Synch.h"
+#include "ace/SString.h"
+
+// Listing 2 code/ch16
+class Workers : public ACE_Task<ACE_MT_SYNCH>
+{
+public:
+ Workers ()
+ { }
+
+ virtual int svc (void)
+ {
+ while (1)
+ {
+ ACE_Message_Block *mb = 0;
+ if (this->getq (mb) == -1)
+ {
+ ACE_DEBUG ((LM_INFO,
+ ACE_TEXT ("(%t) Shutting down\n")));
+ break;
+ }
+
+ // Process the message.
+ process_message (mb);
+ }
+
+ return 0;
+ }
+ // Listing 2
+
+private:
+ void process_message (ACE_Message_Block *mb)
+ {
+ ACE_TRACE (ACE_TEXT ("Workers::process_message"));
+ int msgId;
+ ACE_OS::memcpy (&msgId, mb->rd_ptr (), sizeof(int));
+ mb->release ();
+
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("(%t) Started processing message %d\n"),
+ msgId));
+ ACE_OS::sleep (3);
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("(%t) Finished processing message %d\n"),
+ msgId));
+ }
+};
+
+// Listing 1 code/ch16
+class Manager : public ACE_Task<ACE_MT_SYNCH>
+{
+public:
+ enum {POOL_SIZE = 5, MAX_TIMEOUT = 5};
+
+ Manager () : shutdown_(0)
+ {
+ ACE_TRACE (ACE_TEXT ("Manager::Manager"));
+ }
+
+ int svc (void)
+ {
+ ACE_TRACE (ACE_TEXT ("Manager::svc"));
+
+ ACE_DEBUG ((LM_INFO, ACE_TEXT ("(%t) Manager started\n")));
+
+ // Create pool.
+ Workers pool;
+ pool.activate (THR_NEW_LWP | THR_JOINABLE, POOL_SIZE);
+
+ while (!done ())
+ {
+ ACE_Message_Block *mb = 0;
+ ACE_Time_Value tv ((long)MAX_TIMEOUT);
+ tv += ACE_OS::time (0);
+
+ // Get a message request.
+ if (this->getq (mb, &tv) < 0)
+ {
+ pool.msg_queue ()->deactivate ();
+ pool.wait ();
+ break;
+ }
+
+ // Ask the worker pool to do the job.
+ pool.putq (mb);
+ }
+
+ return 0;
+ }
+
+private:
+ int done (void);
+
+ int shutdown_;
+};
+// Listing 1
+
+int Manager::done (void)
+{
+ return (shutdown_ == 1);
+}
+
+
+int ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ Manager tp;
+ tp.activate ();
+
+ // Wait for a moment every time you send a message.
+ ACE_Time_Value tv;
+ tv.msec (100);
+
+ ACE_Message_Block *mb;
+ for (int i = 0; i < 30; i++)
+ {
+ ACE_NEW_RETURN
+ (mb, ACE_Message_Block(sizeof(int)), -1);
+
+ ACE_OS::memcpy (mb->wr_ptr (), &i, sizeof(int));
+
+ ACE_OS::sleep (tv);
+
+ // Add a new work item.
+ tp.putq (mb);
+ }
+
+ ACE_Thread_Manager::instance ()->wait ();
+ return 0;
+}
+
+#else
+#include "ace/OS_main.h"
+#include "ace/OS_NS_stdio.h"
+
+int ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ ACE_OS::puts (ACE_TEXT ("This example requires threads."));
+ return 0;
+}
+
+#endif /* ACE_HAS_THREADS */
diff --git a/ACE/examples/APG/ThreadPools/ThreadPool.cpp b/ACE/examples/APG/ThreadPools/ThreadPool.cpp
new file mode 100644
index 00000000000..684762efcbf
--- /dev/null
+++ b/ACE/examples/APG/ThreadPools/ThreadPool.cpp
@@ -0,0 +1,271 @@
+// $Id$
+
+#include "ace/config-lite.h"
+#if defined (ACE_HAS_THREADS)
+
+#include "ace/OS_NS_string.h"
+#include "ace/OS_NS_time.h"
+#include "ace/Task.h"
+#include "ace/Containers.h"
+#include "ace/Synch.h"
+#include "ace/SString.h"
+#include "ace/Method_Request.h"
+#include "ace/Future.h"
+#include "ace/Activation_Queue.h"
+
+class Worker;
+
+class IManager
+{
+public:
+ virtual ~IManager (void) { }
+
+ virtual int return_to_work (Worker *worker) = 0;
+};
+
+// Listing 2 code/ch16
+class Worker : public ACE_Task<ACE_MT_SYNCH>
+{
+public:
+ Worker (IManager *manager) : manager_(manager) { }
+
+ virtual int svc (void)
+ {
+ thread_id_ = ACE_Thread::self ();
+ while (1)
+ {
+ ACE_Message_Block *mb = 0;
+ if (this->getq (mb) == -1)
+ ACE_ERROR_BREAK
+ ((LM_ERROR, ACE_TEXT ("%p\n"), ACE_TEXT ("getq")));
+ if (mb->msg_type () == ACE_Message_Block::MB_HANGUP)
+ {
+ ACE_DEBUG ((LM_INFO,
+ ACE_TEXT ("(%t) Shutting down\n")));
+ mb->release ();
+ break;
+ }
+ // Process the message.
+ process_message (mb);
+ // Return to work.
+ this->manager_->return_to_work (this);
+ }
+
+ return 0;
+ }
+ // Listing 2
+
+ ACE_thread_t thread_id (void)
+ {
+ return thread_id_;
+ }
+
+private:
+ void process_message (ACE_Message_Block *mb)
+ {
+ ACE_TRACE (ACE_TEXT ("Worker::process_message"));
+ int msgId;
+ ACE_OS::memcpy (&msgId, mb->rd_ptr (), sizeof(int));
+ mb->release ();
+
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("(%t) Started processing message %d\n"),
+ msgId));
+ ACE_OS::sleep (3);
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("(%t) Finished processing message %d\n"),
+ msgId));
+ }
+
+ IManager *manager_;
+ ACE_thread_t thread_id_;
+};
+
+// Listing 1 code/ch16
+class Manager: public ACE_Task<ACE_MT_SYNCH>, private IManager
+{
+public:
+ enum {POOL_SIZE = 5, MAX_TIMEOUT = 5};
+
+ Manager ()
+ : shutdown_(0), workers_lock_(), workers_cond_(workers_lock_)
+ {
+ ACE_TRACE (ACE_TEXT ("Manager::Manager"));
+ }
+
+ int svc (void)
+ {
+ ACE_TRACE (ACE_TEXT ("Manager::svc"));
+
+ ACE_DEBUG ((LM_INFO, ACE_TEXT ("(%t) Manager started\n")));
+
+ // Create pool.
+ create_worker_pool ();
+
+ while (!done ())
+ {
+ ACE_Message_Block *mb = 0;
+ ACE_Time_Value tv ((long)MAX_TIMEOUT);
+ tv += ACE_OS::time (0);
+
+ // Get a message request.
+ if (this->getq (mb, &tv) < 0)
+ {
+ shut_down ();
+ break;
+ }
+
+ // Choose a worker.
+ Worker *worker = 0;
+ {
+ ACE_GUARD_RETURN (ACE_Thread_Mutex,
+ worker_mon, this->workers_lock_, -1);
+
+ while (this->workers_.is_empty ())
+ workers_cond_.wait ();
+
+ this->workers_.dequeue_head (worker);
+ }
+
+ // Ask the worker to do the job.
+ worker->putq (mb);
+ }
+
+ return 0;
+ }
+
+ int shut_down (void);
+
+ ACE_thread_t thread_id (Worker *worker);
+
+ virtual int return_to_work (Worker *worker)
+ {
+ ACE_GUARD_RETURN (ACE_Thread_Mutex,
+ worker_mon, this->workers_lock_, -1);
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("(%t) Worker %d returning to work.\n"),
+ worker->thr_mgr ()->thr_self ()));
+ this->workers_.enqueue_tail (worker);
+ this->workers_cond_.signal ();
+
+ return 0;
+ }
+
+private:
+ int create_worker_pool (void)
+ {
+ ACE_GUARD_RETURN (ACE_Thread_Mutex,
+ worker_mon,
+ this->workers_lock_,
+ -1);
+ for (int i = 0; i < POOL_SIZE; i++)
+ {
+ Worker *worker;
+ ACE_NEW_RETURN (worker, Worker (this), -1);
+ this->workers_.enqueue_tail (worker);
+ worker->activate ();
+ }
+
+ return 0;
+ }
+
+ int done (void);
+
+private:
+ int shutdown_;
+ ACE_Thread_Mutex workers_lock_;
+ ACE_Condition<ACE_Thread_Mutex> workers_cond_;
+ ACE_Unbounded_Queue<Worker* > workers_;
+};
+// Listing 1
+
+int Manager::done (void)
+{
+ return (shutdown_ == 1);
+}
+
+int
+Manager::shut_down (void)
+{
+ ACE_TRACE (ACE_TEXT ("Manager::shut_down"));
+ ACE_Unbounded_Queue<Worker* >::ITERATOR iter =
+ this->workers_.begin ();
+ Worker **worker_ptr = 0;
+ do
+ {
+ iter.next (worker_ptr);
+ Worker *worker = (*worker_ptr);
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("(%t) Attempting shutdown of %d\n"),
+ thread_id (worker)));
+
+ // Send the hangup message.
+ ACE_Message_Block *mb;
+ ACE_NEW_RETURN
+ (mb,
+ ACE_Message_Block(0,
+ ACE_Message_Block::MB_HANGUP),
+ -1);
+ worker->putq (mb);
+
+ // Wait for the exit.
+ worker->wait ();
+
+ ACE_ASSERT (worker->msg_queue ()->is_empty ());
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("(%t) Worker %d shut down.\n)"),
+ thread_id (worker)));
+ delete worker;
+ }
+ while (iter.advance ());
+
+ shutdown_ = 1;
+
+ return 0;
+}
+
+ACE_thread_t
+Manager::thread_id (Worker *worker)
+{
+ return worker->thread_id ();
+}
+
+
+int ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ Manager tp;
+ tp.activate ();
+
+ // Wait for a moment every time you send a message.
+ ACE_Time_Value tv;
+ tv.msec (100);
+
+ ACE_Message_Block *mb;
+ for (int i = 0; i < 30; i++)
+ {
+ ACE_NEW_RETURN
+ (mb, ACE_Message_Block(sizeof(int)), -1);
+
+ ACE_OS::memcpy (mb->wr_ptr (), &i, sizeof(int));
+
+ ACE_OS::sleep (tv);
+
+ // Add a new work item.
+ tp.putq (mb);
+ }
+
+ ACE_Thread_Manager::instance ()->wait ();
+ return 0;
+}
+
+#else
+#include "ace/OS_main.h"
+#include "ace/OS_NS_stdio.h"
+
+int ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ ACE_OS::puts (ACE_TEXT ("This example requires threads."));
+ return 0;
+}
+
+#endif /* ACE_HAS_THREADS */
diff --git a/ACE/examples/APG/ThreadPools/threadpools.mpc b/ACE/examples/APG/ThreadPools/threadpools.mpc
new file mode 100644
index 00000000000..1bb9a860920
--- /dev/null
+++ b/ACE/examples/APG/ThreadPools/threadpools.mpc
@@ -0,0 +1,38 @@
+// -*- MPC -*-
+// $Id$
+
+project(Futures) : aceexe {
+ avoids += ace_for_tao
+ exename = Futures
+ Source_Files {
+ Futures.cpp
+ }
+}
+
+project(LF ThreadPool) : aceexe {
+ exename = LF_ThreadPool
+ Source_Files {
+ LF_ThreadPool.cpp
+ }
+}
+
+project(Task ThreadPool) : aceexe {
+ exename = Task_ThreadPool
+ Source_Files {
+ Task_ThreadPool.cpp
+ }
+}
+
+project(ThreadPool) : aceexe {
+ exename = ThreadPool
+ Source_Files {
+ ThreadPool.cpp
+ }
+}
+
+project(TP Reactor) : aceexe {
+ exename = TP_Reactor
+ Source_Files {
+ TP_Reactor.cpp
+ }
+}
diff --git a/ACE/examples/APG/ThreadSafety/.cvsignore b/ACE/examples/APG/ThreadSafety/.cvsignore
new file mode 100644
index 00000000000..7fe1b99d03f
--- /dev/null
+++ b/ACE/examples/APG/ThreadSafety/.cvsignore
@@ -0,0 +1,16 @@
+Atomic_Op
+Atomic_Op
+Barrier
+Barrier
+Mutex
+Mutex
+RW_Lock
+RW_Lock
+Semaphore
+Semaphore
+TSS
+TSS
+Tokens
+Tokens
+Tokens_Deadlock
+Tokens_Deadlock
diff --git a/ACE/examples/APG/ThreadSafety/Atomic_Op.cpp b/ACE/examples/APG/ThreadSafety/Atomic_Op.cpp
new file mode 100644
index 00000000000..d315d433a66
--- /dev/null
+++ b/ACE/examples/APG/ThreadSafety/Atomic_Op.cpp
@@ -0,0 +1,127 @@
+// $Id$
+
+#include "ace/Synch.h"
+#include "ace/Task.h"
+#include "ace/Log_Msg.h"
+#include "ace/Atomic_Op.h"
+
+#if defined(RUNNING_ON_UNSAFE_MULTIPROCESSOR)
+// Listing 1 code/ch14
+typedef ACE_Atomic_Op<ACE_Thread_Mutex, unsigned int> SafeUInt;
+// Listing 1
+// Listing 2 code/ch14
+typedef ACE_Atomic_Op<ACE_Thread_Mutex, int> SafeInt;
+// Listing 2
+#else
+typedef ACE_Atomic_Op<ACE_Null_Mutex, unsigned int> SafeUInt;
+typedef ACE_Atomic_Op<ACE_Null_Mutex, int> SafeInt;
+#endif /* RUNNING_ON_UNSAFE_MULTIPROCESSOR) */
+
+static const unsigned int Q_SIZE = 2;
+static const int MAX_PROD = 10;
+
+// Listing 3 code/ch14
+class Producer : public ACE_Task_Base
+{
+public:
+ Producer (int *buf, SafeUInt &in, SafeUInt &out)
+ : buf_(buf), in_(in), out_(out)
+ { }
+
+ int svc (void)
+ {
+ SafeInt itemNo = 0;
+ while (1)
+ {
+ // Busy wait.
+ do
+ { }
+ while (in_.value () - out_.value () == Q_SIZE);
+
+ itemNo++;
+ buf_[in_.value () % Q_SIZE] = itemNo.value ();
+ in_++;
+
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Produced %d \n"),
+ itemNo.value ()));
+
+ if (check_termination (itemNo.value ()))
+ break;
+ }
+
+ return 0;
+ }
+
+ int check_termination (int item)
+ {
+ return (item == MAX_PROD);
+ }
+
+private:
+ int * buf_;
+ SafeUInt& in_;
+ SafeUInt& out_;
+};
+
+class Consumer : public ACE_Task_Base
+{
+public:
+ Consumer (int *buf, SafeUInt &in, SafeUInt& out)
+ : buf_(buf), in_(in), out_(out)
+ { }
+
+ int svc (void)
+ {
+ while (1)
+ {
+ int item;
+
+ // Busy wait.
+ do
+ { }
+ while (in_.value () - out_.value () == 0);
+
+ item = buf_[out_.value () % Q_SIZE];
+ out_++;
+
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Consumed %d\n"),
+ item));
+
+ if (check_termination (item))
+ break;
+ }
+
+ return 0;
+ }
+
+ int check_termination (int item)
+ {
+ return (item == MAX_PROD);
+ }
+
+private:
+ int * buf_;
+ SafeUInt& in_;
+ SafeUInt& out_;
+};
+// Listing 3
+
+// Listing 4 code/ch14
+int ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ int shared_buf[Q_SIZE];
+ SafeUInt in = 0;
+ SafeUInt out = 0;
+
+ Producer producer (shared_buf, in, out);
+ Consumer consumer (shared_buf, in, out);
+
+ producer.activate();
+ consumer.activate();
+ producer.wait();
+ consumer.wait();
+
+ return 0;
+}
+// Listing 4
+
diff --git a/ACE/examples/APG/ThreadSafety/Barrier.cpp b/ACE/examples/APG/ThreadSafety/Barrier.cpp
new file mode 100644
index 00000000000..b07a08f0cee
--- /dev/null
+++ b/ACE/examples/APG/ThreadSafety/Barrier.cpp
@@ -0,0 +1,91 @@
+// $Id$
+
+#include "ace/config-lite.h"
+#if defined (ACE_HAS_THREADS)
+
+#include "ace/OS_NS_stdlib.h"
+#include "ace/OS_NS_time.h"
+#include "ace/Task.h"
+#include "ace/Synch.h"
+
+// Listing 2 code/ch14
+class HA_CommandHandler : public ACE_Task<ACE_MT_SYNCH>
+{
+public:
+ enum { N_THREADS = 5 };
+
+ HA_CommandHandler (ACE_Barrier& startup_barrier,
+ ACE_Barrier &shutdown_barrier)
+ : startup_barrier_(startup_barrier),
+ shutdown_barrier_(shutdown_barrier)
+ { }
+
+ void initialize_handler (void);
+ int handle_command_requests (void);
+
+ int svc (void)
+ {
+ initialize_handler ();
+ startup_barrier_.wait ();
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("(%t: %D) Started\n")));
+
+ while (handle_command_requests () > 0)
+ ;
+
+ shutdown_barrier_.wait ();
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("(%t: %D) Ended\n")));
+
+ return 0;
+ }
+
+private:
+ ACE_Barrier& startup_barrier_;
+ ACE_Barrier& shutdown_barrier_;
+};
+// Listing 2
+
+void
+HA_CommandHandler::initialize_handler (void)
+{
+ ACE_Time_Value tv (0, ACE_OS::rand () * 100);
+ timespec_t t = (timespec_t)tv;
+ ACE_OS::nanosleep (&t);
+}
+
+int
+HA_CommandHandler::handle_command_requests (void)
+{
+ ACE_Time_Value tv (0, ACE_OS::rand () * 100);
+ timespec_t t = (timespec_t)tv;
+
+ // Simulate work.
+ ACE_OS::nanosleep (&t);
+
+ return -1;
+}
+
+// Listing 1 code/ch14
+int ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ ACE_Barrier startup_barrier (HA_CommandHandler::N_THREADS);
+ ACE_Barrier shutdown_barrier (HA_CommandHandler::N_THREADS);
+
+ HA_CommandHandler handler (startup_barrier, shutdown_barrier);
+ handler.activate (THR_NEW_LWP | THR_JOINABLE,
+ HA_CommandHandler::N_THREADS);
+ handler.wait ();
+ return 0;
+}
+// Listing 1
+
+#else
+#include "ace/OS_main.h"
+#include "ace/OS_NS_stdio.h"
+
+int ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ ACE_OS::puts (ACE_TEXT ("This example requires threads."));
+ return 0;
+}
+
+#endif /* ACE_HAS_THREADS */
diff --git a/ACE/examples/APG/ThreadSafety/ClientContext.h b/ACE/examples/APG/ThreadSafety/ClientContext.h
new file mode 100644
index 00000000000..bcd58fc4599
--- /dev/null
+++ b/ACE/examples/APG/ThreadSafety/ClientContext.h
@@ -0,0 +1,30 @@
+/**
+ * $Id$
+ *
+ * Sample code from The ACE Programmer's Guide,
+ * copyright 2003 Addison-Wesley. All Rights Reserved.
+ */
+
+#ifndef __CLIENTCONTEXT_H_
+#define __CLIENTCONTEXT_H_
+
+#include "ace/Hash_Map_Manager.h"
+#include "ace/Synch.h"
+
+typedef ACE_Hash_Map_Manager<const char *, void *, ACE_Null_Mutex>
+Map;
+
+// Listing 1 code/ch14
+// Client-specific context information.
+class ClientContext
+{
+public:
+ void *get_attribute (const char *name);
+ void set_attribute (const char *name, void *value);
+
+private:
+ Map attributeMap_;
+};
+// Listing 1
+
+#endif /* __CLIENTCONTEXT_H_ */
diff --git a/ACE/examples/APG/ThreadSafety/Makefile.am b/ACE/examples/APG/ThreadSafety/Makefile.am
new file mode 100644
index 00000000000..e7c52980171
--- /dev/null
+++ b/ACE/examples/APG/ThreadSafety/Makefile.am
@@ -0,0 +1,141 @@
+## Process this file with automake to create Makefile.in
+##
+## $Id$
+##
+## This file was generated by MPC. Any changes made directly to
+## this file will be lost the next time it is generated.
+##
+## MPC Command:
+## /acebuilds/ACE_wrappers-repository/bin/mwc.pl -include /acebuilds/MPC/config -include /acebuilds/MPC/templates -feature_file /acebuilds/ACE_wrappers-repository/local.features -noreldefs -type automake -exclude build,Kokyu
+
+ACE_BUILDDIR = $(top_builddir)
+ACE_ROOT = $(top_srcdir)
+
+
+## Makefile.Atomic_Op.am
+noinst_PROGRAMS = Atomic_Op
+
+Atomic_Op_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+Atomic_Op_SOURCES = \
+ Atomic_Op.cpp \
+ ClientContext.h
+
+Atomic_Op_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Makefile.Barrier.am
+noinst_PROGRAMS += Barrier
+
+Barrier_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+Barrier_SOURCES = \
+ Barrier.cpp \
+ ClientContext.h
+
+Barrier_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Makefile.Mutex.am
+noinst_PROGRAMS += Mutex
+
+Mutex_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+Mutex_SOURCES = \
+ Mutex.cpp \
+ ClientContext.h
+
+Mutex_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Makefile.RW_Lock.am
+
+if !BUILD_ACE_FOR_TAO
+noinst_PROGRAMS += RW_Lock
+
+RW_Lock_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+RW_Lock_SOURCES = \
+ RW_Lock.cpp \
+ ClientContext.h
+
+RW_Lock_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+endif !BUILD_ACE_FOR_TAO
+
+## Makefile.Semaphore.am
+
+if !BUILD_ACE_FOR_TAO
+noinst_PROGRAMS += Semaphore
+
+Semaphore_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+Semaphore_SOURCES = \
+ Semaphore.cpp \
+ ClientContext.h
+
+Semaphore_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+endif !BUILD_ACE_FOR_TAO
+
+## Makefile.TSS.am
+noinst_PROGRAMS += TSS
+
+TSS_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+TSS_SOURCES = \
+ TSS.cpp \
+ ClientContext.h
+
+TSS_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Makefile.Tokens.am
+noinst_PROGRAMS += Tokens
+
+Tokens_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+Tokens_SOURCES = \
+ Tokens.cpp \
+ ClientContext.h
+
+Tokens_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Makefile.Tokens_Deadlock.am
+noinst_PROGRAMS += Tokens_Deadlock
+
+Tokens_Deadlock_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+Tokens_Deadlock_SOURCES = \
+ Tokens_Deadlock.cpp \
+ ClientContext.h
+
+Tokens_Deadlock_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Clean up template repositories, etc.
+clean-local:
+ -rm -f *~ *.bak *.rpo *.sym lib*.*_pure_* core core.*
+ -rm -f gcctemp.c gcctemp so_locations *.ics
+ -rm -rf cxx_repository ptrepository ti_files
+ -rm -rf templateregistry ir.out
+ -rm -rf ptrepository SunWS_cache Templates.DB
diff --git a/ACE/examples/APG/ThreadSafety/Mutex.cpp b/ACE/examples/APG/ThreadSafety/Mutex.cpp
new file mode 100644
index 00000000000..aa21665222c
--- /dev/null
+++ b/ACE/examples/APG/ThreadSafety/Mutex.cpp
@@ -0,0 +1,73 @@
+// $Id$
+
+#include "ace/config-lite.h"
+#if defined (ACE_HAS_THREADS)
+
+#include "ace/Synch.h"
+
+class LogMessage
+{
+public:
+ enum { CRITICAL, NORMAL};
+
+ virtual ~LogMessage ()
+ {
+ }
+
+ virtual int priority (void)
+ {
+ return NORMAL;
+ }
+};
+
+class CriticalLogMessage : public LogMessage
+{
+ virtual int priority (void)
+ {
+ return LogMessage::CRITICAL;
+ }
+};
+
+// Listing 1 code/ch14
+typedef ACE_Thread_Mutex MUTEX;
+class Logger
+{
+public:
+ void log (LogMessage *msg)
+ {
+ ACE_GUARD (MUTEX, mon, mutex_);
+ if (msg->priority () == LogMessage::CRITICAL)
+ logCritical (msg);
+ }
+
+ void logCritical (LogMessage *)
+ {
+ // Acquires the same mutex as log()!
+ ACE_GUARD(MUTEX, mon, mutex_);
+ }
+
+private:
+ MUTEX mutex_;
+};
+
+static Logger logger;
+
+int ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ CriticalLogMessage cm;
+ logger.log(&cm); // Will cause deadlock.
+ return 0;
+}
+// Listing 1
+
+#else
+#include "ace/OS_main.h"
+#include "ace/OS_NS_stdio.h"
+
+int ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ ACE_OS::puts (ACE_TEXT ("This example requires threads."));
+ return 0;
+}
+
+#endif /* ACE_HAS_THREADS */
diff --git a/ACE/examples/APG/ThreadSafety/RW_Lock.cpp b/ACE/examples/APG/ThreadSafety/RW_Lock.cpp
new file mode 100644
index 00000000000..83f1287bbdb
--- /dev/null
+++ b/ACE/examples/APG/ThreadSafety/RW_Lock.cpp
@@ -0,0 +1,139 @@
+// $Id$
+
+#include "ace/config-lite.h"
+#if defined (ACE_HAS_THREADS)
+
+#include "ace/Synch.h"
+#include "ace/Containers.h"
+#include "ace/Task.h"
+
+class Device
+{
+public:
+ Device (int id) : id_(id)
+ { }
+
+ int id_;
+};
+
+typedef ACE_DLList<Device> DeviceList;
+typedef ACE_DLList_Iterator<Device> DeviceListIterator;
+
+// Listing 1 code/ch14
+class HA_DiscoveryAgent
+{
+public:
+ void add_device (Device *device)
+ {
+ ACE_WRITE_GUARD (ACE_RW_Thread_Mutex, mon, rwmutex_);
+ list_add_item_i (device);
+ }
+
+ void remove_device (Device *device)
+ {
+ ACE_READ_GUARD (ACE_RW_Thread_Mutex, mon, rwmutex_);
+ list_remove_item_i(device);
+ }
+
+ int contains_device (Device *device)
+ {
+ ACE_READ_GUARD_RETURN
+ (ACE_RW_Thread_Mutex, mon, rwmutex_, -1);
+ return list_contains_item_i (device);
+ }
+
+private:
+ void list_add_item_i (Device * device);
+ int list_contains_item_i (Device * device);
+ void list_remove_item_i (Device* device);
+
+private:
+ DeviceList deviceList_;
+ ACE_RW_Thread_Mutex rwmutex_;
+};
+// Listing 1
+
+void
+HA_DiscoveryAgent::list_add_item_i (Device *device)
+{
+ deviceList_.insert_tail (device);
+}
+
+int
+HA_DiscoveryAgent::list_contains_item_i (Device *device)
+{
+ DeviceListIterator iter (deviceList_);
+ while (!iter.done ())
+ {
+ if (iter.next () == device)
+ return 1;
+ iter++;
+ }
+
+ return 0;
+}
+
+void
+HA_DiscoveryAgent::list_remove_item_i (Device *device)
+{
+ DeviceListIterator iter (deviceList_);
+ while (!iter.done ())
+ {
+ if (iter.next () == device)
+ {
+ iter.remove ();
+ break;
+ }
+ iter++;
+ }
+}
+
+static Device *devices[100];
+
+class Runner : public ACE_Task_Base
+{
+public:
+ Runner(HA_DiscoveryAgent &agent) : agent_(agent)
+ { }
+
+ virtual int svc (void)
+ {
+ ACE_ASSERT(agent_.contains_device(devices[9]) == 1);
+ agent_.remove_device (devices[9]);
+ ACE_ASSERT(agent_.contains_device(devices[9]) == 0);
+ return 0;
+ }
+
+private:
+ HA_DiscoveryAgent &agent_;
+};
+
+int ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ HA_DiscoveryAgent agent;
+
+ for (int i = 0; i < 100; i++)
+ {
+ devices[i] = new Device (i);
+ agent.add_device (devices[i]);
+ }
+
+ Runner runner (agent);
+ runner.activate ();
+
+ runner.wait ();
+
+ return 0;
+}
+
+#else
+#include "ace/OS_main.h"
+#include "ace/OS_NS_stdio.h"
+
+int ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ ACE_OS::puts (ACE_TEXT ("This example requires threads."));
+ return 0;
+}
+
+#endif /* ACE_HAS_THREADS */
diff --git a/ACE/examples/APG/ThreadSafety/Semaphore.cpp b/ACE/examples/APG/ThreadSafety/Semaphore.cpp
new file mode 100644
index 00000000000..47a85d86874
--- /dev/null
+++ b/ACE/examples/APG/ThreadSafety/Semaphore.cpp
@@ -0,0 +1,147 @@
+// $Id$
+
+#include "ace/config-lite.h"
+#if defined (ACE_HAS_THREADS)
+
+#include "ace/OS_NS_string.h"
+#include "ace/Task.h"
+#include "ace/Synch.h"
+
+// Listing 2 code/ch14
+class Consumer : public ACE_Task<ACE_MT_SYNCH>
+{
+public:
+ enum { N_THREADS = 5 };
+
+ Consumer (ACE_Semaphore& psema, ACE_Semaphore& csema)
+ : psema_(psema), csema_(csema), exit_condition_(0)
+ { }
+
+ int svc (void)
+ {
+ while (!is_closed ())
+ consume_item ();
+ return 0;
+ }
+
+ void consume_item ()
+ {
+ csema_.acquire ();
+ if (!is_closed ())
+ {
+ ACE_Message_Block *mb;
+ this->getq (mb);
+ if (mb->msg_type () == ACE_Message_Block::MB_HANGUP)
+ {
+ shutdown ();
+ mb->release ();
+ return;
+ }
+ else
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("(%t) Consumed %d\n"),
+ *((int*)mb->rd_ptr ())));
+ mb->release();
+ }
+ psema_.release ();
+ }
+ }
+
+ void shutdown (void)
+ {
+ exit_condition_ = 1;
+ this->msg_queue ()->deactivate ();
+ csema_.release (N_THREADS);
+ }
+
+ int is_closed (void)
+ {
+ return exit_condition_;
+ }
+
+private:
+ ACE_Semaphore& psema_;
+ ACE_Semaphore& csema_;
+ int exit_condition_;
+};
+// Listing 2
+// Listing 1 code/ch14
+class Producer : public ACE_Task_Base
+{
+public:
+ enum { MAX_PROD = 128 };
+
+ Producer (ACE_Semaphore& psema, ACE_Semaphore& csema,
+ Consumer &consumer)
+ : psema_(psema), csema_(csema), consumer_(consumer)
+ { }
+
+ int svc (void)
+ {
+ for (int i = 0; i <= MAX_PROD; i++)
+ produce_item (i);
+ hang_up ();
+ return 0;
+ }
+
+ void produce_item (int item)
+ {
+ psema_.acquire ();
+ ACE_Message_Block *mb
+ = new ACE_Message_Block (sizeof (int),
+ ACE_Message_Block::MB_DATA);
+ ACE_OS::memcpy (mb->wr_ptr (), &item, sizeof item);
+ mb->wr_ptr (sizeof (int));
+ this->consumer_.putq (mb);
+
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("(%t) Produced %d\n"), item));
+ csema_.release();
+ }
+
+ void hang_up ()
+ {
+ psema_.acquire ();
+ ACE_Message_Block *mb =
+ new ACE_Message_Block (0, ACE_Message_Block::MB_HANGUP);
+ this->consumer_.putq (mb);
+ csema_.release ();
+ }
+
+private:
+ ACE_Semaphore& psema_;
+ ACE_Semaphore& csema_;
+ Consumer& consumer_;
+};
+// Listing 1
+// Listing 3 code/ch14
+int ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ ACE_Semaphore psem (5);
+ ACE_Semaphore csem (0);
+
+ Consumer consumer (psem, csem);
+ Producer producer (psem, csem, consumer);
+
+ producer.activate ();
+ consumer.activate (THR_NEW_LWP | THR_JOINABLE,
+ Consumer::N_THREADS);
+
+ producer.wait ();
+ consumer.wait ();
+
+ return 0;
+}
+// Listing 3
+
+#else
+#include "ace/OS_main.h"
+#include "ace/OS_NS_stdio.h"
+
+int ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ ACE_OS::puts (ACE_TEXT ("This example requires threads."));
+ return 0;
+}
+
+#endif /* ACE_HAS_THREADS */
diff --git a/ACE/examples/APG/ThreadSafety/TSS.cpp b/ACE/examples/APG/ThreadSafety/TSS.cpp
new file mode 100644
index 00000000000..8cc875cb3ee
--- /dev/null
+++ b/ACE/examples/APG/ThreadSafety/TSS.cpp
@@ -0,0 +1,75 @@
+// $Id$
+
+#include "ace/config-lite.h"
+#if defined (ACE_HAS_THREADS)
+
+#include "ace/Synch.h"
+#include "ace/Task.h"
+#include "ClientContext.h"
+
+
+void*
+ClientContext::get_attribute (const char *name)
+{
+ void * value = 0;
+ attributeMap_.find (name, value);
+ return value;
+}
+
+void
+ClientContext::set_attribute (const char *name, void *value)
+{
+ attributeMap_.bind (name, value);
+}
+
+// Listing 2 code/ch14
+class HA_CommandHandler : public ACE_Task<ACE_MT_SYNCH>
+{
+public:
+ virtual int svc (void)
+ {
+ ACE_thread_t tid = this->thr_mgr ()->thr_self ();
+ // Set our identifier in TSS.
+ this->tss_ctx_->set_attribute ("thread_id", &tid);
+
+ while (handle_requests () > 0)
+ ;
+
+ return 0;
+ }
+
+ int handle_requests (void)
+ {
+ ACE_thread_t *tid =
+ (ACE_thread_t*)this->tss_ctx_->get_attribute ("thread_id");
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("(%t) TSS TID: %d \n"),
+ *tid));
+
+ // do work.
+ return -1;
+ }
+
+private:
+ ACE_TSS<ClientContext> tss_ctx_;
+};
+// Listing 2
+
+int ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ HA_CommandHandler handler;
+ handler.activate (THR_NEW_LWP | THR_JOINABLE, 5);
+ handler.wait ();
+ return 0;
+}
+
+#else
+#include "ace/OS_main.h"
+#include "ace/OS_NS_stdio.h"
+
+int ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ ACE_OS::puts (ACE_TEXT ("This example requires threads."));
+ return 0;
+}
+
+#endif /* ACE_HAS_THREADS */
diff --git a/ACE/examples/APG/ThreadSafety/Tokens.cpp b/ACE/examples/APG/ThreadSafety/Tokens.cpp
new file mode 100644
index 00000000000..13adff1febb
--- /dev/null
+++ b/ACE/examples/APG/ThreadSafety/Tokens.cpp
@@ -0,0 +1,102 @@
+// $Id$
+
+#include "ace/Local_Tokens.h"
+#include "ace/Token_Manager.h"
+#include "ace/Task.h"
+#include "ace/OS_NS_time.h"
+
+#if defined (ACE_HAS_TOKENS_LIBRARY)
+
+class Device;
+
+// Listing 1 code/ch14
+class HA_Device_Repository
+{
+public:
+
+ enum { N_DEVICES = 100 };
+
+ HA_Device_Repository ()
+ {
+ for (int i = 0; i < N_DEVICES; i++)
+ tokens_[i] = new ACE_Local_Mutex (0, 0, 1);
+ }
+
+ ~HA_Device_Repository ()
+ {
+ for (int i = 0; i < N_DEVICES; i++)
+ delete tokens_[i];
+ }
+
+ int update_device (int device_id, char *commands)
+ {
+ this->tokens_[device_id]->acquire ();
+
+ Device *curr_device = this->devices_[device_id];
+ internal_do (curr_device);
+
+ this->tokens_[device_id]->release ();
+
+ return 0;
+ }
+
+ void internal_do (Device *device);
+
+private:
+ Device *devices_[N_DEVICES];
+ ACE_Local_Mutex *tokens_[N_DEVICES];
+ unsigned int seed_;
+};
+// Listing 1
+
+void
+HA_Device_Repository::internal_do (Device *device)
+{
+ ACE_UNUSED_ARG (device); // Real code would use this.
+ ACE_Time_Value tv (0, ACE_OS::rand_r (this->seed_) % 10000);
+ timespec_t t = (timespec_t)tv;
+ ACE_OS::nanosleep (&t);
+}
+
+// Listing 2 code/ch14
+class HA_CommandHandler : public ACE_Task_Base
+{
+public:
+ enum { N_THREADS = 5 };
+
+ HA_CommandHandler (HA_Device_Repository &rep) : rep_(rep)
+ { }
+
+ int svc (void)
+ {
+ for (int i = 0; i < HA_Device_Repository::N_DEVICES; i++)
+ rep_.update_device (i, "");
+ return 0;
+ }
+
+private:
+ HA_Device_Repository &rep_;
+};
+
+int ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ HA_Device_Repository rep;
+ HA_CommandHandler handler (rep);
+ handler.activate (THR_NEW_LWP | THR_JOINABLE,
+ HA_CommandHandler::N_THREADS);
+ handler.wait ();
+ return 0;
+}
+// Listing 2
+
+#else /* defined (ACE_HAS_TOKENS_LIBRARY) */
+
+int ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("local tokens not supported ")
+ ACE_TEXT ("on this platform\n")));
+ return 0;
+}
+
+#endif /* defined (ACE_HAS_TOKENS_LIBRARY) */
diff --git a/ACE/examples/APG/ThreadSafety/Tokens_Deadlock.cpp b/ACE/examples/APG/ThreadSafety/Tokens_Deadlock.cpp
new file mode 100644
index 00000000000..f6c6d22491f
--- /dev/null
+++ b/ACE/examples/APG/ThreadSafety/Tokens_Deadlock.cpp
@@ -0,0 +1,69 @@
+// $Id$
+
+#include "ace/Local_Tokens.h"
+#include "ace/Task.h"
+#include "ace/OS_NS_unistd.h"
+
+#if defined (ACE_HAS_TOKENS_LIBRARY)
+
+// Listing 1 code/ch14
+class ThreadOne : public ACE_Task_Base
+{
+public:
+ virtual int svc (void)
+ {
+ ACE_Local_Mutex mutex1 (ACE_TEXT ("resource1"),
+ 0, // Deadlock detection enabled.
+ 1);// Debugging enabled.
+ mutex1.acquire ();
+ ACE_OS::sleep (2);
+ ACE_Local_Mutex mutex2 (ACE_TEXT ("resource2"), 0, 1);
+ mutex2.acquire ();
+ return 0;
+ }
+};
+
+class ThreadTwo : public ACE_Task_Base
+{
+public:
+ virtual int svc (void)
+ {
+ ACE_Local_Mutex mutex2 (ACE_TEXT ("resource2"),
+ 0, // Deadlock detection enabled.
+ 1);// Debugging enabled.
+ mutex2.acquire ();
+ ACE_OS::sleep (2);
+ ACE_Local_Mutex mutex1 (ACE_TEXT ("resource1"),
+ 0, // Deadlock detection enabled.
+ 1);// Debugging enabled.
+ mutex1.acquire ();
+ return 0;
+ }
+};
+
+int ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ ThreadOne t1;
+ ThreadTwo t2;
+
+ t1.activate ();
+ ACE_OS::sleep (1);
+ t2.activate ();
+ t1.wait ();
+ t2.wait ();
+
+ return 0;
+}
+// Listing 1
+
+#else /* defined (ACE_HAS_TOKENS_LIBRARY) */
+
+int ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("local tokens not supported ")
+ ACE_TEXT ("on this platform\n")));
+ return 0;
+}
+
+#endif /* defined (ACE_HAS_TOKENS_LIBRARY) */
diff --git a/ACE/examples/APG/ThreadSafety/threadsafety.mpc b/ACE/examples/APG/ThreadSafety/threadsafety.mpc
new file mode 100644
index 00000000000..3598d274917
--- /dev/null
+++ b/ACE/examples/APG/ThreadSafety/threadsafety.mpc
@@ -0,0 +1,60 @@
+// -*- MPC -*-
+// $Id$
+
+project(Atomic Op) : aceexe {
+ exename = Atomic_Op
+ Source_Files {
+ Atomic_Op.cpp
+ }
+}
+
+project(Barrier) : aceexe {
+ exename = Barrier
+ Source_Files {
+ Barrier.cpp
+ }
+}
+
+project(Mutex) : aceexe {
+ exename = Mutex
+ Source_Files {
+ Mutex.cpp
+ }
+}
+
+project(RW Lock) : aceexe {
+ avoids += ace_for_tao
+ exename = RW_Lock
+ Source_Files {
+ RW_Lock.cpp
+ }
+}
+
+project(Semaphore) : aceexe {
+ avoids += ace_for_tao
+ exename = Semaphore
+ Source_Files {
+ Semaphore.cpp
+ }
+}
+
+project(Tokens) : aceexe {
+ exename = Tokens
+ Source_Files {
+ Tokens.cpp
+ }
+}
+
+project(Tokens Deadlock) : aceexe {
+ exename = Tokens_Deadlock
+ Source_Files {
+ Tokens_Deadlock.cpp
+ }
+}
+
+project(TSS) : aceexe {
+ exename = TSS
+ Source_Files {
+ TSS.cpp
+ }
+}
diff --git a/ACE/examples/APG/Threads/.cvsignore b/ACE/examples/APG/Threads/.cvsignore
new file mode 100644
index 00000000000..feb9ec3ab97
--- /dev/null
+++ b/ACE/examples/APG/Threads/.cvsignore
@@ -0,0 +1,12 @@
+Activate
+Activate
+Condition_Variables
+Condition_Variables
+Guards
+Guards
+Message_Blocks
+Message_Blocks
+Message_Queue
+Message_Queue
+Mutexes
+Mutexes
diff --git a/ACE/examples/APG/Threads/Activate.cpp b/ACE/examples/APG/Threads/Activate.cpp
new file mode 100644
index 00000000000..2afa6316f91
--- /dev/null
+++ b/ACE/examples/APG/Threads/Activate.cpp
@@ -0,0 +1,33 @@
+// $Id$
+
+// Listing 1 code/ch12
+#include "ace/Task.h"
+#include "ace/OS_NS_unistd.h"
+
+class HA_CommandHandler : public ACE_Task_Base
+{
+public:
+ virtual int svc (void)
+ {
+ ACE_DEBUG
+ ((LM_DEBUG, ACE_TEXT ("(%t) Handler Thread running\n")));
+ ACE_OS::sleep (4);
+ return 0;
+ }
+};
+
+int ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ ACE_DEBUG
+ ((LM_DEBUG, ACE_TEXT ("(%t) Main Thread running\n")));
+
+ HA_CommandHandler handler;
+ int result = handler.activate ();
+ ACE_ASSERT (result == 0);
+
+ ACE_UNUSED_ARG (result);
+
+ handler.wait ();
+ return 0;
+}
+// Listing 1
diff --git a/ACE/examples/APG/Threads/Condition_Variables.cpp b/ACE/examples/APG/Threads/Condition_Variables.cpp
new file mode 100644
index 00000000000..ccb29895032
--- /dev/null
+++ b/ACE/examples/APG/Threads/Condition_Variables.cpp
@@ -0,0 +1,118 @@
+// $Id$
+
+#include "ace/config-lite.h"
+#if defined (ACE_HAS_THREADS)
+
+#include "ace/Task.h"
+#include "ace/Synch.h"
+
+// Listing 1 code/ch12
+class HA_Device_Repository
+{
+public:
+ HA_Device_Repository() : owner_(0)
+ { }
+
+ int is_free (void)
+ { return (this->owner_ == 0); }
+
+ int is_owner (ACE_Task_Base* tb)
+ { return (this->owner_ == tb); }
+
+ ACE_Task_Base *get_owner (void)
+ { return this->owner_; }
+
+ void set_owner (ACE_Task_Base *owner)
+ { this->owner_ = owner; }
+
+ int update_device (int device_id);
+
+private:
+ ACE_Task_Base * owner_;
+};
+// Listing 1
+
+class HA_CommandHandler : public ACE_Task_Base
+{
+public:
+ enum {NUM_USES = 10};
+
+ HA_CommandHandler (HA_Device_Repository& rep,
+ ACE_Condition<ACE_Thread_Mutex> &wait,
+ ACE_Thread_Mutex& mutex)
+ : rep_(rep), waitCond_(wait), mutex_(mutex)
+ { }
+
+ virtual int svc (void);
+
+private:
+ HA_Device_Repository &rep_;
+ ACE_Condition<ACE_Thread_Mutex> &waitCond_;
+ ACE_Thread_Mutex &mutex_;
+};
+// Listing 2 code/ch12
+int
+HA_CommandHandler::svc (void)
+{
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("(%t) Handler Thread running\n")));
+
+ for (int i = 0; i < NUM_USES; i++)
+ {
+ this->mutex_.acquire ();
+ while (!this->rep_.is_free ())
+ this->waitCond_.wait ();
+ this->rep_.set_owner (this);
+ this->mutex_.release ();
+
+ this->rep_.update_device (i);
+
+ ACE_ASSERT (this->rep_.is_owner (this));
+ this->rep_.set_owner (0);
+
+ this->waitCond_.signal ();
+ }
+
+ return 0;
+}
+// Listing 2
+int
+HA_Device_Repository::update_device (int device_id)
+{
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("(%t) Updating device %d\n"),
+ device_id));
+
+ ACE_OS::sleep (1);
+ return 0;
+}
+// Listing 3 code/ch12
+int ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ HA_Device_Repository rep;
+ ACE_Thread_Mutex rep_mutex;
+ ACE_Condition<ACE_Thread_Mutex> wait (rep_mutex);
+
+ HA_CommandHandler handler1 (rep, wait, rep_mutex);
+ HA_CommandHandler handler2 (rep, wait, rep_mutex);
+
+ handler1.activate ();
+ handler2.activate ();
+
+ handler1.wait ();
+ handler2.wait ();
+
+ return 0;
+}
+// Listing 3
+
+#else
+#include "ace/OS_main.h"
+#include "ace/OS_NS_stdio.h"
+
+int ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ ACE_OS::puts (ACE_TEXT ("This example requires threads."));
+ return 0;
+}
+
+#endif /* ACE_HAS_THREADS */
diff --git a/ACE/examples/APG/Threads/Guards.cpp b/ACE/examples/APG/Threads/Guards.cpp
new file mode 100644
index 00000000000..7ef23e1e4da
--- /dev/null
+++ b/ACE/examples/APG/Threads/Guards.cpp
@@ -0,0 +1,95 @@
+// $Id$
+#include "ace/config-lite.h"
+#if defined (ACE_HAS_THREADS)
+
+#include "ace/OS_main.h"
+#include "ace/OS_Memory.h"
+#include "ace/Guard_T.h"
+#include "ace/Log_Msg.h"
+#include "ace/Thread_Mutex.h"
+
+// This file exists primarily to get code into the book to show different
+// ways to do the same thing. For complete context and explanation, please
+// see APG chapter 12.
+
+class HA_Device_Repository {
+public:
+ int update_device (int device_id);
+
+private:
+ ACE_Thread_Mutex mutex_;
+};
+
+class Object {
+};
+static Object *object;
+
+#if 0
+// This is less-desired way to do this...
+
+// Listing 1 code/ch12
+int
+HA_Device_Repository::update_device (int device_id)
+{
+ this->mutex_.acquire ();
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("(%t) Updating device %d\n"),
+ device_id));
+
+ // Allocate a new object.
+ ACE_NEW_RETURN (object, Object, -1);
+ // ...
+ // Use the object
+
+ this->mutex_.release ();
+}
+// Listing 1
+// Listing 2 code/ch12
+int
+HA_Device_Repository::update_device (int device_id)
+{
+ // Construct a guard specifying the type of the mutex as
+ // a template parameter and passing in the mutex to hold
+ // as a parameter.
+ ACE_Guard<ACE_Thread_Mutex> guard (this->mutex_);
+
+ // This can throw an exception that is not caught here.
+ ACE_NEW_RETURN (object, Object, -1);
+ // ..
+ // Use the object.
+ // ..
+ // Guard is destroyed, automatically releasing the lock.
+}
+// Listing 2
+#endif /* 0 */
+
+// Listing 3 code/ch12
+int
+HA_Device_Repository::update_device (int /* device_id */)
+{
+ ACE_GUARD_RETURN (ACE_Thread_Mutex, mon, mutex_, -1);
+
+ ACE_NEW_RETURN (object, Object, -1);
+ // Use the object.
+ // ...
+ return 0;
+}
+// Listing 3
+
+int ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ HA_Device_Repository rep;
+ rep.update_device (42);
+ return 0;
+}
+
+#else
+#include "ace/OS_main.h"
+#include "ace/OS_NS_stdio.h"
+
+int ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ ACE_OS::puts (ACE_TEXT ("This example requires threads."));
+ return 0;
+}
+
+#endif /* ACE_HAS_THREADS */
diff --git a/ACE/examples/APG/Threads/Makefile.am b/ACE/examples/APG/Threads/Makefile.am
new file mode 100644
index 00000000000..a5a1b77d76a
--- /dev/null
+++ b/ACE/examples/APG/Threads/Makefile.am
@@ -0,0 +1,104 @@
+## Process this file with automake to create Makefile.in
+##
+## $Id$
+##
+## This file was generated by MPC. Any changes made directly to
+## this file will be lost the next time it is generated.
+##
+## MPC Command:
+## /acebuilds/ACE_wrappers-repository/bin/mwc.pl -include /acebuilds/MPC/config -include /acebuilds/MPC/templates -feature_file /acebuilds/ACE_wrappers-repository/local.features -noreldefs -type automake -exclude build,Kokyu
+
+ACE_BUILDDIR = $(top_builddir)
+ACE_ROOT = $(top_srcdir)
+
+## Makefile.Activate.am
+noinst_PROGRAMS = Activate
+
+Activate_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+Activate_SOURCES = \
+ Activate.cpp \
+ Message_Receiver.h
+
+Activate_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Makefile.Condition_Variables.am
+noinst_PROGRAMS += Condition_Variables
+
+Condition_Variables_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+Condition_Variables_SOURCES = \
+ Condition_Variables.cpp \
+ Message_Receiver.h
+
+Condition_Variables_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Makefile.Guards.am
+noinst_PROGRAMS += Guards
+
+Guards_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+Guards_SOURCES = \
+ Guards.cpp \
+ Message_Receiver.h
+
+Guards_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Makefile.Message_Blocks.am
+noinst_PROGRAMS += Message_Blocks
+
+Message_Blocks_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+Message_Blocks_SOURCES = \
+ Message_Blocks.cpp \
+ Message_Receiver.h
+
+Message_Blocks_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Makefile.Message_Queue.am
+noinst_PROGRAMS += Message_Queue
+
+Message_Queue_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+Message_Queue_SOURCES = \
+ Message_Queue.cpp \
+ Message_Receiver.h
+
+Message_Queue_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Makefile.Mutexes.am
+noinst_PROGRAMS += Mutexes
+
+Mutexes_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+Mutexes_SOURCES = \
+ Mutexes.cpp \
+ Message_Receiver.h
+
+Mutexes_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Clean up template repositories, etc.
+clean-local:
+ -rm -f *~ *.bak *.rpo *.sym lib*.*_pure_* core core.*
+ -rm -f gcctemp.c gcctemp so_locations *.ics
+ -rm -rf cxx_repository ptrepository ti_files
+ -rm -rf templateregistry ir.out
+ -rm -rf ptrepository SunWS_cache Templates.DB
diff --git a/ACE/examples/APG/Threads/Message_Blocks.cpp b/ACE/examples/APG/Threads/Message_Blocks.cpp
new file mode 100644
index 00000000000..96cbf3e8cfe
--- /dev/null
+++ b/ACE/examples/APG/Threads/Message_Blocks.cpp
@@ -0,0 +1,50 @@
+// $Id$
+
+#include "ace/OS_main.h"
+#include "ace/OS_Memory.h"
+#include "ace/OS_NS_stdio.h"
+#include "ace/OS_NS_string.h"
+#include "ace/Log_Msg.h"
+#include "ace/Message_Block.h"
+
+int ACE_TMAIN (int, ACE_TCHAR **)
+{
+#if 0
+// Just for the book...
+
+// Listing 1 code/ch12
+ ACE_Message_Block *mb;
+ ACE_NEW_RETURN (mb, ACE_Message_Block (128), -1);
+
+ const char *deviceAddr= "Dev#12";
+ mb->copy (deviceAddr, ACE_OS::strlen (deviceAddr)+1);
+// Listing 1
+#endif /* 0 */
+// Listing 2 code/ch12
+ ACE_Message_Block *mb;
+ ACE_NEW_RETURN (mb, ACE_Message_Block (128), -1);
+
+ const char *commandSeq= "CommandSeq#14";
+ ACE_OS::sprintf (mb->wr_ptr (), commandSeq);
+ // Move the wr_ptr() forward in the buffer by the
+ // amount of data we just put in.
+ mb->wr_ptr (ACE_OS::strlen (commandSeq) +1);
+// Listing 2
+// Listing 3 code/ch12
+ ACE_DEBUG((LM_DEBUG,
+ ACE_TEXT ("Command Sequence --> %C\n"),
+ mb->rd_ptr ()));
+ mb->rd_ptr (ACE_OS::strlen (mb->rd_ptr ())+1);
+ mb->release ();
+// Listing 3
+// Listing 4 code/ch12
+ // Send a hangup notification to the receiver.
+ ACE_NEW_RETURN
+ (mb, ACE_Message_Block (128, ACE_Message_Block::MB_HANGUP), -1);
+ // Send an error notification to the receiver.
+ mb->msg_type (ACE_Message_Block::MB_ERROR);
+// Listing 4
+ mb->release ();
+
+ return 0;
+}
diff --git a/ACE/examples/APG/Threads/Message_Queue.cpp b/ACE/examples/APG/Threads/Message_Queue.cpp
new file mode 100644
index 00000000000..3544d6bcefa
--- /dev/null
+++ b/ACE/examples/APG/Threads/Message_Queue.cpp
@@ -0,0 +1,179 @@
+// $Id$
+
+#include "ace/config-lite.h"
+#if defined (ACE_HAS_THREADS)
+
+#include "ace/SOCK_Acceptor.h"
+#include "ace/Acceptor.h"
+#include "Message_Receiver.h"
+
+// Listing 5 code/ch12
+int
+HA_CommandHandler::svc (void)
+{
+ while(1)
+ {
+ ACE_Message_Block *mb;
+ if (this->getq (mb) == -1)
+ break;
+ if (mb->msg_type () == ACE_Message_Block::MB_HANGUP)
+ {
+ mb->release ();
+ break;
+ }
+ else
+ {
+ // Get header pointer, then move past header to payload.
+ DeviceCommandHeader *dch
+ = (DeviceCommandHeader*)mb->rd_ptr ();
+ mb->rd_ptr (sizeof (DeviceCommandHeader));
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("Message for device #%d with ")
+ ACE_TEXT ("command payload of:\n%s"),
+ dch->deviceId_, mb->rd_ptr ()));
+ this->rep_.update_device (dch->deviceId_,
+ mb->rd_ptr ());
+ mb->release ();
+ }
+ }
+
+ ACE_Reactor::instance ()->end_reactor_event_loop ();
+
+ return 0;
+}
+// Listing 5
+
+// Listing 4 code/ch12
+ACE_Message_Block *
+Message_Receiver::shut_down_message (void)
+{
+ ACE_Message_Block *mb;
+ ACE_NEW_RETURN
+ (mb, ACE_Message_Block (0, ACE_Message_Block::MB_HANGUP), 0);
+ return mb;
+}
+// Listing 4
+
+int
+Message_Receiver::read_header (DeviceCommandHeader *dch)
+{
+ ssize_t result =
+ this->peer ().recv_n (dch, sizeof (DeviceCommandHeader));
+ if (result <= 0)
+ ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("%p\n"),
+ ACE_TEXT ("Recieve Failure")),
+ -1);
+ return 0;
+}
+// Listing 3 code/ch12
+int
+Message_Receiver::copy_payload (ACE_Message_Block *mb,
+ int payload_length)
+{
+ ssize_t result =
+ this->peer ().recv_n (mb->wr_ptr (), payload_length);
+
+ if (result <= 0)
+ {
+ mb->release ();
+ return -1;
+ }
+
+ mb->wr_ptr (payload_length);
+ return 0;
+}
+// Listing 3
+// Listing 2 code/ch12
+int
+Message_Receiver::handle_input (ACE_HANDLE)
+{
+ DeviceCommandHeader dch;
+ if (this->read_header (&dch) < 0)
+ return -1;
+
+ if (dch.deviceId_ < 0)
+ {
+ // Handle shutdown.
+ this->handler_->putq (shut_down_message ());
+ return -1;
+ }
+
+ ACE_Message_Block *mb;
+ ACE_NEW_RETURN
+ (mb, ACE_Message_Block (dch.length_ + sizeof dch), -1);
+ // Copy the header.
+ mb->copy ((const char*)&dch, sizeof dch);
+ // Copy the payload.
+ if (this->copy_payload (mb, dch.length_) < 0)
+ ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("%p\n"),
+ ACE_TEXT ("Recieve Failure")), -1);
+ // Pass it off to the handler thread.
+ this->handler_->putq (mb);
+ return 0;
+}
+// Listing 2
+
+static void report_usage (int argc, ACE_TCHAR *argv[])
+{
+ if (argc < 2)
+ {
+ ACE_DEBUG ((LM_ERROR, ACE_TEXT ("%s port\n"), argv[1]));
+ ACE_OS::exit (-1);
+ }
+}
+
+
+class Acceptor : public ACE_Acceptor<Message_Receiver, ACE_SOCK_ACCEPTOR>
+{
+public:
+ Acceptor(HA_CommandHandler *handler) : handler_(handler)
+ { }
+
+protected:
+ virtual int make_svc_handler (Message_Receiver *&mr)
+ {
+ ACE_NEW_RETURN (mr, Message_Receiver (handler_), -1);
+ return 0;
+ }
+
+private:
+ HA_CommandHandler *handler_;
+};
+
+int ACE_TMAIN (int argc, ACE_TCHAR *argv[])
+{
+ report_usage (argc, argv);
+
+ u_short port = ACE_OS::atoi (argv[1]);
+
+ HA_Device_Repository rep;
+ HA_CommandHandler handler (rep);
+ ACE_ASSERT(handler.activate()==0);
+ //start up the handler.
+
+ Acceptor acceptor (&handler);
+ ACE_INET_Addr addr (port);
+ if (acceptor.open (addr) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("%p\n"),
+ ACE_TEXT ("Failed to open connection")), -1);
+
+ ACE_Reactor::instance()->run_reactor_event_loop ();
+ //run the reactive event loop
+
+ handler.wait ();
+ //reap the handler before exiting.
+
+ return 0;
+}
+
+#else
+#include "ace/OS_main.h"
+#include "ace/OS_NS_stdio.h"
+
+int ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ ACE_OS::puts (ACE_TEXT ("This example requires threads."));
+ return 0;
+}
+
+#endif /* ACE_HAS_THREADS */
diff --git a/ACE/examples/APG/Threads/Message_Receiver.h b/ACE/examples/APG/Threads/Message_Receiver.h
new file mode 100644
index 00000000000..dee0731f007
--- /dev/null
+++ b/ACE/examples/APG/Threads/Message_Receiver.h
@@ -0,0 +1,90 @@
+/**
+ * $Id$
+ *
+ * Sample code from The ACE Programmer's Guide,
+ * copyright 2003 Addison-Wesley. All Rights Reserved.
+ */
+
+#ifndef __MESSAGE_RECEIVER_H_
+#define __MESSAGE_RECEIVER_H_
+
+#include "ace/Log_Msg.h"
+#include "ace/Message_Block.h"
+#include "ace/SOCK_Stream.h"
+#include "ace/Svc_Handler.h"
+#include "ace/Synch.h"
+#include "ace/Task.h"
+
+// Listing 1 code/ch12
+struct DeviceCommandHeader
+{
+ int length_;
+ int deviceId_;
+};
+// Listing 1
+
+class HA_Device_Repository
+{
+public:
+ HA_Device_Repository ();
+
+ int update_device (int device_id, char *commands);
+
+private:
+ ACE_Task_Base *owner_;
+};
+
+HA_Device_Repository::HA_Device_Repository ()
+{ }
+
+int
+HA_Device_Repository::update_device (int, char *)
+{
+ return 0;
+}
+
+class HA_CommandHandler : public ACE_Task<ACE_MT_SYNCH>
+{
+public:
+ HA_CommandHandler (HA_Device_Repository &rep) : rep_(rep)
+ { }
+
+ virtual int svc();
+
+private:
+ HA_Device_Repository &rep_;
+};
+
+class Message_Receiver :
+ public ACE_Svc_Handler<ACE_SOCK_STREAM, ACE_MT_SYNCH>
+{
+public:
+ Message_Receiver () : handler_(0)
+ {
+ ACE_ASSERT(0);
+ }
+
+ Message_Receiver (HA_CommandHandler *ch) : handler_(ch)
+ { }
+
+ ACE_Message_Block *shut_down_message (void);
+
+ virtual int handle_input (ACE_HANDLE fd);
+
+ virtual int handle_close (ACE_HANDLE = ACE_INVALID_HANDLE,
+ ACE_Reactor_Mask = ACE_Event_Handler::ALL_EVENTS_MASK)
+ {
+ this->peer ().close ();
+ delete this;
+ return 0;
+ }
+
+private:
+ int read_header (DeviceCommandHeader *dch);
+ int copy_payload (ACE_Message_Block *mb, int payload_length);
+
+private:
+ HA_CommandHandler *handler_;
+};
+
+#endif /* __MESSAGE_RECEIVER_H */
diff --git a/ACE/examples/APG/Threads/Mutexes.cpp b/ACE/examples/APG/Threads/Mutexes.cpp
new file mode 100644
index 00000000000..ca5ebcdcbe4
--- /dev/null
+++ b/ACE/examples/APG/Threads/Mutexes.cpp
@@ -0,0 +1,75 @@
+// $Id$
+
+#include "ace/config-lite.h"
+#if defined (ACE_HAS_THREADS)
+
+#include "ace/Synch.h"
+#include "ace/Task.h"
+
+// Listing 1 code/ch12
+class HA_Device_Repository
+{
+public:
+ HA_Device_Repository ()
+ { }
+
+ void update_device (int device_id)
+ {
+ mutex_.acquire ();
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("(%t) Updating device %d\n"),
+ device_id));
+ ACE_OS::sleep (1);
+ mutex_.release ();
+ }
+
+private:
+ ACE_Thread_Mutex mutex_;
+};
+// Listing 1
+// Listing 2 code/ch12
+class HA_CommandHandler : public ACE_Task_Base
+{
+public:
+ enum {NUM_USES = 10};
+
+ HA_CommandHandler (HA_Device_Repository& rep) : rep_(rep)
+ { }
+
+ virtual int svc (void)
+ {
+ ACE_DEBUG
+ ((LM_DEBUG, ACE_TEXT ("(%t) Handler Thread running\n")));
+ for (int i=0; i < NUM_USES; i++)
+ this->rep_.update_device (i);
+ return 0;
+ }
+
+private:
+ HA_Device_Repository & rep_;
+};
+
+int ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ HA_Device_Repository rep;
+ HA_CommandHandler handler1 (rep);
+ HA_CommandHandler handler2 (rep);
+ handler1.activate ();
+ handler2.activate ();
+
+ handler1.wait ();
+ handler2.wait ();
+ return 0;
+}
+// Listing 2
+
+#else
+#include "ace/OS_main.h"
+#include "ace/OS_NS_stdio.h"
+
+int ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ ACE_OS::puts (ACE_TEXT ("This example requires threads."));
+ return 0;
+}
+
+#endif /* ACE_HAS_THREADS */
diff --git a/ACE/examples/APG/Threads/threads.mpc b/ACE/examples/APG/Threads/threads.mpc
new file mode 100644
index 00000000000..a980a867d26
--- /dev/null
+++ b/ACE/examples/APG/Threads/threads.mpc
@@ -0,0 +1,44 @@
+// -*- MPC -*-
+// $Id$
+
+project(Activate) : aceexe {
+ exename = Activate
+ Source_Files {
+ Activate.cpp
+ }
+}
+
+project(Condition Variables) : aceexe {
+ exename = Condition_Variables
+ Source_Files {
+ Condition_Variables.cpp
+ }
+}
+
+project(Guards) : aceexe {
+ exename = Guards
+ Source_Files {
+ Guards.cpp
+ }
+}
+
+project(Message Blocks) : aceexe {
+ exename = Message_Blocks
+ Source_Files {
+ Message_Blocks.cpp
+ }
+}
+
+project(Message Queue) : aceexe {
+ exename = Message_Queue
+ Source_Files {
+ Message_Queue.cpp
+ }
+}
+
+project(Mutexes) : aceexe {
+ exename = Mutexes
+ Source_Files {
+ Mutexes.cpp
+ }
+}
diff --git a/ACE/examples/APG/Timers/.cvsignore b/ACE/examples/APG/Timers/.cvsignore
new file mode 100644
index 00000000000..9137f2e897a
--- /dev/null
+++ b/ACE/examples/APG/Timers/.cvsignore
@@ -0,0 +1,8 @@
+Alarm
+Alarm
+Task
+Task
+Timers
+Timers
+Upcall
+Upcall
diff --git a/ACE/examples/APG/Timers/Alarm.cpp b/ACE/examples/APG/Timers/Alarm.cpp
new file mode 100644
index 00000000000..c12d39b367d
--- /dev/null
+++ b/ACE/examples/APG/Timers/Alarm.cpp
@@ -0,0 +1,57 @@
+// $Id$
+
+#include "ace/OS_NS_unistd.h"
+#include "ace/OS_NS_sys_time.h"
+
+// Listing 1 code/ch20
+#include "ace/Timer_Queue_Adapters.h"
+#include "ace/Timer_Heap.h"
+
+typedef ACE_Async_Timer_Queue_Adapter<ACE_Timer_Heap> Timer;
+// Listing 1
+
+class CB : public ACE_Event_Handler
+{
+public:
+ CB (int id) : id_(id) { }
+
+ virtual int handle_timeout (const ACE_Time_Value &,
+ const void *arg)
+ {
+ ACE_TRACE (ACE_TEXT ("CB::handle_timeout"));
+
+ const int *val = static_cast<const int*> (arg);
+ ACE_ASSERT ((*val) == id_);
+
+ ACE_UNUSED_ARG (val);
+
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Timer expired\n")));
+ return 0;
+ }
+
+private:
+ int id_;
+};
+
+// Listing 2 code/ch20
+int ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ // Create the timer such that it blocks all signals
+ // when it goes off.
+ Timer timer;
+
+ // Schedule a timer to go off 2 seconds later and then
+ // after every 4 seconds.
+ CB cb (1);
+ int arg = 1;
+ ACE_Time_Value initial (2);
+ ACE_Time_Value repeat (4);
+ initial += ACE_OS::gettimeofday ();
+ timer.schedule (&cb, &arg, initial, repeat);
+
+ while (1) // Don't let the main thread exit.
+ ACE_OS::sleep (2);
+ ACE_NOTREACHED (return 0); // Not reached.
+}
+// Listing 2
+
diff --git a/ACE/examples/APG/Timers/CB.cpp b/ACE/examples/APG/Timers/CB.cpp
new file mode 100644
index 00000000000..0a86ae7edeb
--- /dev/null
+++ b/ACE/examples/APG/Timers/CB.cpp
@@ -0,0 +1,70 @@
+// $Id$
+
+#include "ace/Log_Msg.h"
+#include "CB.h"
+#include "TimerDispatcher.h"
+
+CB::CB () : count_(0)
+{
+ ACE_TRACE (ACE_TEXT ("CB::CB"));
+}
+
+// Listing 1 code/ch20
+int CB::handle_timeout (const ACE_Time_Value &,
+ const void *arg)
+{
+ ACE_TRACE (ACE_TEXT ("CB::handle_timeout"));
+
+ const int *val = static_cast<const int*> (arg);
+ ACE_ASSERT ((*val) == timerID_);
+
+ ACE_UNUSED_ARG (val);
+
+ if (count_ == 5)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("Reseting interval for timer %d\n"),
+ timerID_));
+
+ // New interval is 10 ms.
+ ACE_Time_Value interval (0L, 1000L);
+ int status = Timer::instance ()->reset_interval
+ (timerID_, interval);
+#if defined (ACE_NDEBUG)
+ ACE_UNUSED_ARG (status);
+#else
+ ACE_ASSERT (status != -1);
+#endif
+ }
+
+ if (count_++ == 10)
+ {
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Canceling %d\n"),
+ timerID_));
+ ACE_ASSERT ((Timer::instance ()->cancel (this)) != 0);
+ }
+
+ return 0;
+}
+// Listing 1
+
+void
+CB::setID (long timerID)
+{
+ ACE_TRACE (ACE_TEXT ("CB::setID"));
+ timerID_ = timerID;
+}
+
+long
+CB::getID (void)
+{
+ ACE_TRACE (ACE_TEXT ("CB::getID"));
+ return timerID_;
+}
+
+int
+CB::handle_close (ACE_HANDLE, ACE_Reactor_Mask)
+{
+ ACE_TRACE (ACE_TEXT ("CB::handle_close"));
+ return 0;
+}
diff --git a/ACE/examples/APG/Timers/CB.h b/ACE/examples/APG/Timers/CB.h
new file mode 100644
index 00000000000..716ad4e4f50
--- /dev/null
+++ b/ACE/examples/APG/Timers/CB.h
@@ -0,0 +1,36 @@
+/* -*- C++ -*- */
+// $Id$
+
+#if !defined(CB_H)
+#define CB_H
+
+#include "ace/Event_Handler.h"
+
+#include "TimerDispatcher.h"
+
+// Listing 1 code/ch20
+class CB : public ACE_Event_Handler
+{
+public:
+ CB ();
+
+ // Set the timer id that is being handled by this instance.
+ void setID (long timerID);
+
+ // Get the timer id.
+ long getID (void);
+
+ // Handle the timeout.
+ virtual int handle_timeout(const ACE_Time_Value &tv,
+ const void *arg = 0);
+
+ virtual int handle_close (ACE_HANDLE handle,
+ ACE_Reactor_Mask close_mask);
+
+private:
+ long timerID_;
+ int count_;
+};
+// Listing 1
+
+#endif /*CB_H*/
diff --git a/ACE/examples/APG/Timers/Makefile.am b/ACE/examples/APG/Timers/Makefile.am
new file mode 100644
index 00000000000..33976800fec
--- /dev/null
+++ b/ACE/examples/APG/Timers/Makefile.am
@@ -0,0 +1,91 @@
+## Process this file with automake to create Makefile.in
+##
+## $Id$
+##
+## This file was generated by MPC. Any changes made directly to
+## this file will be lost the next time it is generated.
+##
+## MPC Command:
+## /acebuilds/ACE_wrappers-repository/bin/mwc.pl -include /acebuilds/MPC/config -include /acebuilds/MPC/templates -feature_file /acebuilds/ACE_wrappers-repository/local.features -noreldefs -type automake -exclude build,Kokyu
+
+ACE_BUILDDIR = $(top_builddir)
+ACE_ROOT = $(top_srcdir)
+
+## Makefile.Alarm.am
+noinst_PROGRAMS = Alarm
+
+Alarm_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+Alarm_SOURCES = \
+ Alarm.cpp \
+ CB.h \
+ PCB.h \
+ PTimerDispatcher.h \
+ TimerDispatcher.h \
+ Upcall.h
+
+Alarm_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Makefile.Task.am
+noinst_PROGRAMS += Task
+
+Task_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+Task_SOURCES = \
+ Task.cpp \
+ CB.h \
+ PCB.h \
+ PTimerDispatcher.h \
+ TimerDispatcher.h \
+ Upcall.h
+
+Task_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Makefile.Timers.am
+noinst_PROGRAMS += Timers
+
+Timers_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+Timers_SOURCES = \
+ CB.cpp \
+ TimerDispatcher.cpp \
+ Timers.cpp \
+ CB.h \
+ TimerDispatcher.h
+
+Timers_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Makefile.Upcall.am
+noinst_PROGRAMS += Upcall
+
+Upcall_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+Upcall_SOURCES = \
+ PCB.cpp \
+ PTimerDispatcher.cpp \
+ Upcall.cpp \
+ PCB.h \
+ PTimerDispatcher.h \
+ Upcall.h
+
+Upcall_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Clean up template repositories, etc.
+clean-local:
+ -rm -f *~ *.bak *.rpo *.sym lib*.*_pure_* core core.*
+ -rm -f gcctemp.c gcctemp so_locations *.ics
+ -rm -rf cxx_repository ptrepository ti_files
+ -rm -rf templateregistry ir.out
+ -rm -rf ptrepository SunWS_cache Templates.DB
diff --git a/ACE/examples/APG/Timers/PCB.cpp b/ACE/examples/APG/Timers/PCB.cpp
new file mode 100644
index 00000000000..d3401c65116
--- /dev/null
+++ b/ACE/examples/APG/Timers/PCB.cpp
@@ -0,0 +1,79 @@
+// $Id$
+
+#include "ace/Log_Msg.h"
+#include "PCB.h"
+#include "PTimerDispatcher.h"
+
+PCB::PCB() : count_(0)
+{
+ ACE_TRACE (ACE_TEXT ("PCB::PCB"));
+}
+
+PCB::~PCB()
+{
+}
+
+int PCB::handleEvent (const void *arg)
+{
+ ACE_TRACE (ACE_TEXT ("PCB::handle_timeout"));
+
+ const int *val = static_cast<const int*> (arg);
+ ACE_ASSERT ((*val) == timerID_);
+
+ ACE_UNUSED_ARG (val);
+
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT("Timer %d expiry handled by thread %t\n"),
+ timerID_));
+ if (count_ == 5)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("Reseting interval for timer %d\n"),
+ timerID_));
+
+ // New interval is 10 ms.
+ ACE_Time_Value interval (0L, 1000L);
+ if (PTimer::instance ()->reset_interval (timerID_, interval) != -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("reset_interval")),
+ -1);
+ }
+
+ if (count_++ == 10)
+ {
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Canceling %d\n"),
+ timerID_));
+ PTimer::instance ()->cancel (this);
+ }
+
+ return 0;
+}
+
+void
+PCB::setID (long timerID)
+{
+ ACE_TRACE (ACE_TEXT ("PCB::setID"));
+ timerID_ = timerID;
+}
+
+long
+PCB::getID (void) const
+{
+ ACE_TRACE (ACE_TEXT ("PCB::getID"));
+ return timerID_;
+}
+
+int
+PCB::handleClose (void)
+{
+ ACE_TRACE (ACE_TEXT ("PCB::handle_close"));
+ return 0;
+}
+
+int
+PCB::handleCancel (void)
+{
+ ACE_TRACE (ACE_TEXT ("PCB::handleCancel"));
+ return 0;
+}
diff --git a/ACE/examples/APG/Timers/PCB.h b/ACE/examples/APG/Timers/PCB.h
new file mode 100644
index 00000000000..7fdb9d2d1cf
--- /dev/null
+++ b/ACE/examples/APG/Timers/PCB.h
@@ -0,0 +1,29 @@
+/* -*- C++ -*- */
+// $Id$
+
+#if !defined(PCB_H)
+#define PCB_H
+
+// Listing 1 code/ch20
+class PCB
+{
+public:
+ PCB ();
+ virtual ~PCB ();
+
+ // Set/get the timer id that is being handled by this instance.
+ void setID (long timerID);
+ long getID (void) const;
+
+ // Handle a timeout event, cancel, and close.
+ virtual int handleEvent (const void *arg);
+ virtual int handleCancel (void);
+ virtual int handleClose (void);
+
+private:
+ long timerID_;
+ int count_;
+};
+// Listing 1
+
+#endif /*PCB_H*/
diff --git a/ACE/examples/APG/Timers/PTimerDispatcher.cpp b/ACE/examples/APG/Timers/PTimerDispatcher.cpp
new file mode 100644
index 00000000000..405c5771789
--- /dev/null
+++ b/ACE/examples/APG/Timers/PTimerDispatcher.cpp
@@ -0,0 +1,69 @@
+// $Id$
+
+#include "PTimerDispatcher.h"
+
+void PTimer_Dispatcher::wait_for_event (void)
+{
+ ACE_TRACE (ACE_TEXT ("PTimer_Dispatcher::wait_for_event"));
+
+ while (1)
+ {
+ ACE_Time_Value max_tv = timer_queue_->gettimeofday ();
+
+ ACE_Time_Value *this_timeout =
+ this->timer_queue_->calculate_timeout (&max_tv);
+
+ if (*this_timeout == ACE_Time_Value::zero)
+ this->timer_queue_->expire ();
+ else
+ {
+ // Convert to absolute time.
+ ACE_Time_Value next_timeout =
+ timer_queue_->gettimeofday ();
+ next_timeout += *this_timeout;
+ if (this->timer_.wait (&next_timeout) == -1 )
+ this->timer_queue_->expire ();
+ }
+ }
+}
+
+long
+PTimer_Dispatcher::schedule (PCB *cb,
+ void *arg,
+ const ACE_Time_Value &abs_time,
+ const ACE_Time_Value &interval)
+{
+ ACE_TRACE (ACE_TEXT ("PTimer_Dispatcher::schedule_timer"));
+
+ return this->timer_queue_->schedule
+ (cb, arg, abs_time, interval);
+}
+
+int
+PTimer_Dispatcher::cancel (PCB *cb,
+ int dont_call_handle_close)
+{
+ ACE_TRACE (ACE_TEXT ("PTimer_Dispatcher::cancel"));
+ return timer_queue_->cancel (cb, dont_call_handle_close);
+}
+
+void PTimer_Dispatcher::set (PTimerQueue *timer_queue)
+{
+ ACE_TRACE (ACE_TEXT ("PTimer_Dispatcher::set"));
+
+ timer_queue_ = timer_queue;
+}
+
+int
+PTimer_Dispatcher::reset_interval (long timer_id,
+ const ACE_Time_Value &interval)
+{
+ ACE_TRACE (ACE_TEXT ("PTimer_Dispatcher::reset_interval"));
+
+ return timer_queue_->reset_interval (timer_id, interval);
+}
+
+#if defined (ACE_HAS_EXPLICIT_STATIC_TEMPLATE_MEMBER_INSTANTIATION)
+template ACE_Singleton<PTimer_Dispatcher, ACE_Null_Mutex> *
+ ACE_Singleton<PTimer_Dispatcher, ACE_Null_Mutex>::singleton_;
+# endif /* ACE_HAS_EXPLICIT_STATIC_TEMPLATE_MEMBER_INSTANTIATION */
diff --git a/ACE/examples/APG/Timers/PTimerDispatcher.h b/ACE/examples/APG/Timers/PTimerDispatcher.h
new file mode 100644
index 00000000000..8a530f41709
--- /dev/null
+++ b/ACE/examples/APG/Timers/PTimerDispatcher.h
@@ -0,0 +1,39 @@
+/* -*- C++ -*- */
+// $Id$
+
+#if !defined(PTIMER_DISPATCHER_H)
+#define PTIMER_DISPATCHER_H
+
+#include "ace/Singleton.h"
+#include "ace/Synch.h" // needed for ACE_Event
+
+#include "Upcall.h"
+class PCB;
+
+class PTimer_Dispatcher
+{
+public:
+ void wait_for_event (void);
+
+ long schedule (PCB *cb,
+ void *arg,
+ const ACE_Time_Value &abs_time,
+ const ACE_Time_Value &interval);
+
+ int cancel (PCB *cb,
+ int dont_call_handle_close = 1);
+
+ int reset_interval (long timer_id,
+ const ACE_Time_Value &interval);
+
+ void set (PTimerQueue *timer_queue);
+
+private:
+ PTimerQueue *timer_queue_;
+ ACE_Event timer_;
+};
+
+typedef ACE_Singleton<PTimer_Dispatcher, ACE_Null_Mutex> PTimer;
+
+#endif /*TIMER_DISPATCHER_H*/
+
diff --git a/ACE/examples/APG/Timers/Task.cpp b/ACE/examples/APG/Timers/Task.cpp
new file mode 100644
index 00000000000..4774eb1444f
--- /dev/null
+++ b/ACE/examples/APG/Timers/Task.cpp
@@ -0,0 +1,73 @@
+// $Id$
+
+#include "ace/OS_NS_sys_time.h"
+
+// Listing 1 code/ch20
+#include "ace/Timer_Queue_Adapters.h"
+#include "ace/Timer_Heap.h"
+
+typedef ACE_Thread_Timer_Queue_Adapter<ACE_Timer_Heap>
+ ActiveTimer;
+
+// Listing 1
+// Listing 2 code/ch20
+class CB : public ACE_Event_Handler
+{
+public:
+ CB (int id) : id_(id) { }
+
+ virtual int handle_timeout (const ACE_Time_Value &,
+ const void *arg)
+ {
+ ACE_TRACE (ACE_TEXT ("CB::handle_timeout"));
+
+ const int *val = static_cast<const int*> (arg);
+ ACE_ASSERT((*val) == id_);
+
+ ACE_UNUSED_ARG (val);
+
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("Expiry handled by thread %t\n")));
+ return 0;
+ }
+
+private:
+ int id_;
+};
+// Listing 2
+
+// Listing 3 code/ch20
+int ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("the main thread %t has started \n")));
+
+ // Create an "active" timer and start its thread.
+ ActiveTimer atimer;
+ atimer.activate ();
+
+ CB cb1 (1);
+ CB cb2 (2);
+ int arg1 = 1;
+ int arg2 = 2;
+
+ // Schedule timers to go off 3 & 4 seconds from now
+ // and then with an interval of 1.1 seconds.
+ const ACE_Time_Value curr_tv = ACE_OS::gettimeofday ();
+ ACE_Time_Value interval = ACE_Time_Value (1, 100000);
+
+ atimer.schedule (&cb1,
+ &arg1,
+ curr_tv + ACE_Time_Value (3L),
+ interval);
+ atimer.schedule (&cb2,
+ &arg2,
+ curr_tv + ACE_Time_Value (4L),
+ interval);
+
+ ACE_Thread_Manager::instance ()->wait (); // Wait forever.
+
+ return 0;
+}
+// Listing 3
+
diff --git a/ACE/examples/APG/Timers/TimerDispatcher.cpp b/ACE/examples/APG/Timers/TimerDispatcher.cpp
new file mode 100644
index 00000000000..818d762b738
--- /dev/null
+++ b/ACE/examples/APG/Timers/TimerDispatcher.cpp
@@ -0,0 +1,73 @@
+// $Id$
+
+#include "TimerDispatcher.h"
+// Listing 1 code/ch20
+void Timer_Dispatcher::wait_for_event (void)
+{
+ ACE_TRACE (ACE_TEXT ("Timer_Dispatcher::wait_for_event"));
+
+ while (1)
+ {
+ ACE_Time_Value max_tv = timer_queue_->gettimeofday ();
+
+ ACE_Time_Value *this_timeout =
+ this->timer_queue_->calculate_timeout (&max_tv);
+
+ if (*this_timeout == ACE_Time_Value::zero)
+ this->timer_queue_->expire ();
+ else
+ {
+ // Convert to absolute time.
+ ACE_Time_Value next_timeout =
+ timer_queue_->gettimeofday ();
+ next_timeout += *this_timeout;
+ if (this->timer_.wait (&next_timeout) == -1 )
+ this->timer_queue_->expire ();
+ }
+ }
+}
+// Listing 1
+// Listing 2 code/ch20
+long
+Timer_Dispatcher::schedule (ACE_Event_Handler *cb,
+ void *arg,
+ const ACE_Time_Value &abs_time,
+ const ACE_Time_Value &interval)
+{
+ ACE_TRACE (ACE_TEXT ("Timer_Dispatcher::schedule_timer"));
+
+ return this->timer_queue_->schedule
+ (cb, arg, abs_time, interval);
+}
+// Listing 2
+// Listing 3 code/ch20
+int
+Timer_Dispatcher::cancel (ACE_Event_Handler *cb,
+ int dont_call_handle_close)
+{
+ ACE_TRACE (ACE_TEXT ("Timer_Dispatcher::cancel"));
+ return timer_queue_->cancel (cb, dont_call_handle_close);
+}
+// Listing 3
+// Listing 4 code/ch20
+void Timer_Dispatcher::set (ACE_Timer_Queue *timer_queue)
+{
+ ACE_TRACE (ACE_TEXT ("Timer_Dispatcher::set"));
+
+ timer_queue_ = timer_queue;
+}
+// Listing 4
+
+int
+Timer_Dispatcher::reset_interval (long timer_id,
+ const ACE_Time_Value &interval)
+{
+ ACE_TRACE (ACE_TEXT ("Timer_Dispatcher::reset_interval"));
+
+ return timer_queue_->reset_interval(timer_id, interval);
+}
+
+#if defined (ACE_HAS_EXPLICIT_STATIC_TEMPLATE_MEMBER_INSTANTIATION)
+template ACE_Singleton<Timer_Dispatcher, ACE_Null_Mutex> *
+ ACE_Singleton<Timer_Dispatcher, ACE_Null_Mutex>::singleton_;
+# endif /* ACE_HAS_EXPLICIT_STATIC_TEMPLATE_MEMBER_INSTANTIATION */
diff --git a/ACE/examples/APG/Timers/TimerDispatcher.h b/ACE/examples/APG/Timers/TimerDispatcher.h
new file mode 100644
index 00000000000..fc519b77615
--- /dev/null
+++ b/ACE/examples/APG/Timers/TimerDispatcher.h
@@ -0,0 +1,40 @@
+/* -*- C++ -*- */
+// $Id$
+
+#if !defined(TIMER_DISPATCHER_H)
+#define TIMER_DISPATCHER_H
+
+#include "ace/Event_Handler.h"
+#include "ace/Singleton.h"
+#include "ace/Synch.h" // needed for ACE_Event
+#include "ace/Timer_Queue.h"
+
+// Listing 1 code/ch20
+class Timer_Dispatcher
+{
+public:
+ void wait_for_event (void);
+
+ long schedule (ACE_Event_Handler *cb,
+ void *arg,
+ const ACE_Time_Value &abs_time,
+ const ACE_Time_Value &interval);
+
+ int cancel (ACE_Event_Handler *cb,
+ int dont_call_handle_close = 1);
+
+ int reset_interval (long timer_id,
+ const ACE_Time_Value &interval);
+
+ void set (ACE_Timer_Queue *timer_queue);
+
+private:
+ ACE_Timer_Queue *timer_queue_;
+ ACE_Event timer_;
+};
+
+typedef ACE_Singleton<Timer_Dispatcher, ACE_Null_Mutex> Timer;
+// Listing 1
+
+#endif /*TIMER_DISPATCHER_H*/
+
diff --git a/ACE/examples/APG/Timers/Timers.cpp b/ACE/examples/APG/Timers/Timers.cpp
new file mode 100644
index 00000000000..761f03a650c
--- /dev/null
+++ b/ACE/examples/APG/Timers/Timers.cpp
@@ -0,0 +1,58 @@
+// $Id$
+
+// Listing 1 code/ch20
+#include "ace/Timer_Queue.h"
+#include "ace/Timer_Heap.h"
+#include "ace/Timer_Wheel.h"
+#include "ace/Timer_Hash.h"
+#include "ace/Timer_List.h"
+
+#include "CB.h"
+#include "TimerDispatcher.h"
+
+int ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ ACE_Timer_Queue *timer_queue;
+
+#if defined(HEAP)
+
+ ACE_NEW_RETURN (timer_queue, ACE_Timer_Heap, -1);
+#elsif defined(HASH)
+
+ ACE_NEW_RETURN (timer_queue, ACE_Timer_Hash, -1);
+#elsif defined(WHEEL)
+
+ ACE_NEW_RETURN (timer_queue, ACE_Timer_Wheel, -1);
+#else
+
+ ACE_NEW_RETURN (timer_queue, ACE_Timer_List, -1);
+#endif
+
+ // setup the timer queue
+ Timer::instance ()->set (timer_queue);
+
+ CB cb[10];
+ long args[10];
+ for (long i = 0; i < 10 ; i++)
+ {
+ ACE_Time_Value const timeout (i);
+ long timerID =
+ Timer::instance ()->schedule
+ (&cb[i],
+ &args[i],
+ timer_queue->gettimeofday () + (ACE_Time_Value)5,
+ timeout);
+
+ // Set the timerID state variable of the handler.
+ cb[i].setID (timerID);
+
+ // Implicitly send the handler it's timer id.
+ args[i] = timerID;
+ }
+
+ // "run" the timer.
+ Timer::instance ()->wait_for_event ();
+
+ return 0;
+}
+// Listing 1
diff --git a/ACE/examples/APG/Timers/Upcall.cpp b/ACE/examples/APG/Timers/Upcall.cpp
new file mode 100644
index 00000000000..cb00ae6113a
--- /dev/null
+++ b/ACE/examples/APG/Timers/Upcall.cpp
@@ -0,0 +1,172 @@
+// $Id$
+
+#include "ace/OS_NS_sys_time.h"
+#include "ace/Log_Msg.h"
+#include "Upcall.h"
+#include "PTimerDispatcher.h"
+
+// Listing 2 code/ch20
+// The signature of this method changed at ACE 5.4. The 'recurring_timer'
+// parameter was added.
+int
+UpcallHandler::timeout (PTimerQueue &,
+ PCB *handler,
+ const void *arg,
+ int /* recurring_timer */,
+ const ACE_Time_Value &)
+{
+ ACE_TRACE (ACE_TEXT ("UpcallHandler::timeout"));
+
+ return (*handler).handleEvent (arg);
+}
+
+#if 0
+// This method was removed at ACE 5.4. Replaced by cancel_type() and
+// cancel_timer().
+int
+UpcallHandler::cancellation (PTimerQueue &,
+ PCB *handler)
+{
+ ACE_TRACE (ACE_TEXT ("UpcallHandler::cancellation"));
+
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("Handler %d has been cancelled\n"),
+ handler->getID ()));
+
+ return handler->handleCancel ();
+}
+#endif /* 0 */
+
+// This method is called when the timer is canceled
+int
+UpcallHandler::deletion (PTimerQueue &,
+ PCB *handler,
+ const void *)
+{
+ ACE_TRACE (ACE_TEXT ("UpcallHandler::deletion"));
+
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("Handler %d has been deleted\n"),
+ handler->getID ()));
+
+ return handler->handleClose ();
+}
+// Listing 2
+
+// *** The rest of the UpcallHandler methods were added for ACE 5.4 ***
+
+// This method is called when a timer is registered.
+int
+UpcallHandler::registration (PTimerQueue &,
+ PCB *handler,
+ const void *)
+{
+ ACE_TRACE (ACE_TEXT ("UpcallHandler::registration"));
+
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("Handler %d has been registered.\n"),
+ handler->getID ()));
+ return 0;
+}
+
+// This method is called at expiration time, before the actual upcall
+// to the handler is made. ACE uses this to adjust reference counts
+// when needed.
+int
+UpcallHandler::preinvoke (PTimerQueue &,
+ PCB *handler,
+ const void *,
+ int,
+ const ACE_Time_Value &,
+ const void *&)
+{
+ ACE_TRACE (ACE_TEXT ("UpcallHandler::preinvoke"));
+
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("Handler %d is about to upcalled.\n"),
+ handler->getID ()));
+ return 0;
+}
+
+// This method is called at expiration time, after the actual upcall
+// to the handler returns. ACE uses this to adjust reference counts
+// when needed.
+int
+UpcallHandler::postinvoke (PTimerQueue &,
+ PCB *handler,
+ const void *,
+ int,
+ const ACE_Time_Value &,
+ const void *)
+{
+ ACE_TRACE (ACE_TEXT ("UpcallHandler::postinvoke"));
+
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("Handler %d returned from upcall.\n"),
+ handler->getID ()));
+ return 0;
+}
+
+// This method is called when a handler is cancelled
+int
+UpcallHandler::cancel_type (PTimerQueue &,
+ PCB *handler,
+ int dont_call,
+ int &)
+{
+ ACE_TRACE (ACE_TEXT ("UpcallHandler::cancel_type"));
+
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("Handler %d has been cancelled\n"),
+ handler->getID ()));
+ if (!dont_call)
+ return handler->handleCancel ();
+ return 0;
+}
+
+// This method is called when a timer is cancelled
+int
+UpcallHandler::cancel_timer (PTimerQueue &,
+ PCB *handler,
+ int dont_call,
+ int)
+{
+ ACE_TRACE (ACE_TEXT ("UpcallHandler::cancel_timer"));
+
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("Handler %d has been cancelled\n"),
+ handler->getID ()));
+ if (!dont_call)
+ return handler->handleCancel ();
+ return 0;
+}
+
+
+// Listing 3 code/ch20
+int ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ PCB cb1, cb2;
+ cb1.setID (1);
+ cb2.setID (2);
+ int arg1 = 1, arg2 = 2;
+
+ PTimerQueue *timerQueue;
+
+ ACE_NEW_RETURN (timerQueue, PTimerHeap (), -1);
+
+ PTimer::instance ()->set (timerQueue);
+
+ ACE_Time_Value tv = ACE_OS::gettimeofday ();
+ tv += 20L;
+
+ // Schedule two different timers to go off.
+ PTimer::instance ()->schedule (&cb1, &arg1, tv, ACE_Time_Value (1));
+ PTimer::instance ()->schedule (&cb2, &arg2, tv, ACE_Time_Value (2));
+
+ // Run the timer event loop forever.
+ PTimer::instance ()->wait_for_event ();
+
+ return 0;
+}
+// Listing 3
+
diff --git a/ACE/examples/APG/Timers/Upcall.h b/ACE/examples/APG/Timers/Upcall.h
new file mode 100644
index 00000000000..6a154f3b8b1
--- /dev/null
+++ b/ACE/examples/APG/Timers/Upcall.h
@@ -0,0 +1,87 @@
+/* -*- C++ -*- */
+// $Id$
+
+#if !defined(UPCALL_H)
+#define UPCALL_H
+
+#include "ace/Timer_Queue_T.h"
+#include "ace/Timer_Heap_T.h"
+#include "ace/Synch.h"
+
+#include "PCB.h"
+
+// Listing 1 code/ch20
+class UpcallHandler;
+
+typedef ACE_Timer_Queue_T<PCB*, UpcallHandler, ACE_Null_Mutex>
+ PTimerQueue;
+
+// Create a special heap-based timer queue that allows you to
+// control exactly how timer evetns are handled.
+typedef ACE_Timer_Heap_T<PCB*, UpcallHandler, ACE_Null_Mutex>
+ PTimerHeap;
+// Listing 1
+
+class UpcallHandler
+{
+public:
+ // The signature of this method changed at ACE 5.4. The 'recurring_timer'
+ // parameter was added.
+ int timeout (PTimerQueue &timer_queue,
+ PCB *handler,
+ const void *arg,
+ int recurring_timer,
+ const ACE_Time_Value &cur_time);
+
+#if 0
+ // This method was removed at ACE 5.4. Replaced by cancel_type() and
+ // cancel_timer().
+ // This method is called when the timer is canceled.
+ int cancellation (PTimerQueue &timer_queue,
+ PCB *handler);
+#endif
+
+ // This method is called when the timer queue is destroyed and
+ // the timer is still contained in it.
+ int deletion (PTimerQueue &timer_queue,
+ PCB *handler,
+ const void *arg);
+
+ // The following methods don't appear before ACE 5.4, so aren't
+ // referenced in APG (it's based on ACE 5.3).
+
+ // This method is called when a timer is registered.
+ int registration (PTimerQueue &timer_queue,
+ PCB *handler,
+ const void *arg);
+
+ // This method is called before the timer expires.
+ int preinvoke (PTimerQueue &timer_queue,
+ PCB *handler,
+ const void *arg,
+ int recurring_timer,
+ const ACE_Time_Value &cur_time,
+ const void *&upcall_act);
+
+ // This method is called after the timer expires.
+ int postinvoke (PTimerQueue &timer_queue,
+ PCB *handler,
+ const void *arg,
+ int recurring_timer,
+ const ACE_Time_Value &cur_time,
+ const void *upcall_act);
+
+ // This method is called when a handler is cancelled
+ int cancel_type (PTimerQueue &timer_queue,
+ PCB *handler,
+ int dont_call,
+ int &requires_reference_counting);
+
+ // This method is called when a timer is cancelled
+ int cancel_timer (PTimerQueue &timer_queue,
+ PCB *handler,
+ int dont_call,
+ int requires_reference_counting);
+};
+
+#endif /*UPCALL_H*/
diff --git a/ACE/examples/APG/Timers/timers.mpc b/ACE/examples/APG/Timers/timers.mpc
new file mode 100644
index 00000000000..295b2bb97d5
--- /dev/null
+++ b/ACE/examples/APG/Timers/timers.mpc
@@ -0,0 +1,34 @@
+// -*- MPC -*-
+// $Id$
+
+project(Alarm) : aceexe {
+ exename = Alarm
+ Source_Files {
+ Alarm.cpp
+ }
+}
+
+project(Task) : aceexe {
+ exename = Task
+ Source_Files {
+ Task.cpp
+ }
+}
+
+project(Timers) : aceexe {
+ exename = Timers
+ Source_Files {
+ Timers.cpp
+ CB.cpp
+ TimerDispatcher.cpp
+ }
+}
+
+project(Upcall) : aceexe {
+ exename = Upcall
+ Source_Files {
+ Upcall.cpp
+ PCB.cpp
+ PTimerDispatcher.cpp
+ }
+}
diff --git a/ACE/examples/ASX/.cvsignore b/ACE/examples/ASX/.cvsignore
new file mode 100644
index 00000000000..1eb7e8a0b93
--- /dev/null
+++ b/ACE/examples/ASX/.cvsignore
@@ -0,0 +1 @@
+Mess
diff --git a/ACE/examples/ASX/CCM_App/.cvsignore b/ACE/examples/ASX/CCM_App/.cvsignore
new file mode 100644
index 00000000000..955ffdc75d5
--- /dev/null
+++ b/ACE/examples/ASX/CCM_App/.cvsignore
@@ -0,0 +1,4 @@
+client
+client
+server
+server
diff --git a/ACE/examples/ASX/CCM_App/ASX_CCM_App.mpc b/ACE/examples/ASX/CCM_App/ASX_CCM_App.mpc
new file mode 100644
index 00000000000..b5c40beb84c
--- /dev/null
+++ b/ACE/examples/ASX/CCM_App/ASX_CCM_App.mpc
@@ -0,0 +1,26 @@
+// -*- MPC -*-
+// $Id$
+
+project(*Lib) : acelib {
+ sharedname = ccm_app
+ Source_Files {
+ CCM_App.cpp
+ }
+}
+
+project(*Server) : aceexe {
+ exename = server
+ after += ASX_CCM_App_Lib
+ Source_Files {
+ SC_Server.cpp
+ }
+}
+
+project(*Client) : aceexe {
+ exename = client
+ after += ASX_CCM_App_Server
+ Source_Files {
+ SC_Client.cpp
+ }
+}
+
diff --git a/ACE/examples/ASX/CCM_App/CCM_App.cpp b/ACE/examples/ASX/CCM_App/CCM_App.cpp
new file mode 100644
index 00000000000..ac72730edb7
--- /dev/null
+++ b/ACE/examples/ASX/CCM_App/CCM_App.cpp
@@ -0,0 +1,119 @@
+// $Id$
+
+#define ACE_BUILD_SVC_DLL
+
+#include "ace/Stream.h"
+#include "ace/Task.h"
+#include "ace/Module.h"
+#include "ace/svc_export.h"
+
+ACE_RCSID(CCM_App, CCM_App, "$Id$")
+
+typedef ACE_Task<ACE_SYNCH> MT_Task;
+typedef ACE_Stream<ACE_SYNCH> MT_Stream;
+typedef ACE_Module<ACE_SYNCH> MT_Module;
+
+class ACE_Svc_Export Test_Task : public MT_Task
+{
+public:
+ virtual int open (void *);
+ virtual int close (u_long);
+ virtual int init (int, ACE_TCHAR *[]);
+ virtual int fini (void);
+ virtual int suspend (void);
+ virtual int resume (void);
+};
+
+int
+Test_Task::open (void *)
+{
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("opening %s\n"),
+ this->name () ? this->name () : ACE_TEXT ("task")));
+ return 0;
+}
+
+int
+Test_Task::close (u_long)
+{
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("closing %s\n"),
+ this->name () ? this->name () : ACE_TEXT ("task")));
+ return 0;
+}
+
+int
+Test_Task::suspend (void)
+{
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("suspending in %s\n"),
+ this->name () ? this->name () : ACE_TEXT ("task")));
+ return 0;
+}
+
+int
+Test_Task::resume (void)
+{
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("resuming in %s\n"),
+ this->name () ? this->name () : ACE_TEXT ("task")));
+ return 0;
+}
+
+int
+Test_Task::init (int, ACE_TCHAR *[])
+{
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("initializing %s\n"),
+ this->name () ? this->name () : ACE_TEXT ("task")));
+
+ return 0;
+}
+
+int
+Test_Task::fini (void)
+{
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("finalizing %s\n"),
+ this->name () ? this->name () : ACE_TEXT ("task")));
+ return 0;
+}
+
+// Factories used to control configuration.
+
+ACE_SVC_FACTORY_DECLARE (Test_Task)
+ACE_SVC_FACTORY_DEFINE (Test_Task)
+
+// Dynamically linked functions used to control configuration.
+
+extern "C" ACE_Svc_Export MT_Stream *make_stream (void);
+extern "C" ACE_Svc_Export MT_Module *make_da (void);
+extern "C" ACE_Svc_Export MT_Module *make_ea (void);
+extern "C" ACE_Svc_Export MT_Module *make_mr (void);
+
+MT_Stream *
+make_stream (void)
+{
+ return new MT_Stream;
+}
+
+MT_Module *
+make_da (void)
+{
+ return new MT_Module (ACE_TEXT ("Device_Adapter"),
+ new Test_Task, new Test_Task);
+}
+
+MT_Module *
+make_ea (void)
+{
+ return new MT_Module (ACE_TEXT ("Event_Analyzer"),
+ new Test_Task, new Test_Task);
+}
+
+MT_Module *
+make_mr (void)
+{
+ return new MT_Module (ACE_TEXT ("Multicast_Router"),
+ new Test_Task, new Test_Task);
+}
diff --git a/ACE/examples/ASX/CCM_App/Makefile.am b/ACE/examples/ASX/CCM_App/Makefile.am
new file mode 100644
index 00000000000..e4051c952ad
--- /dev/null
+++ b/ACE/examples/ASX/CCM_App/Makefile.am
@@ -0,0 +1,57 @@
+## Process this file with automake to create Makefile.in
+##
+## $Id$
+##
+## This file was generated by MPC. Any changes made directly to
+## this file will be lost the next time it is generated.
+##
+## MPC Command:
+## /acebuilds/ACE_wrappers-repository/bin/mwc.pl -include /acebuilds/MPC/config -include /acebuilds/MPC/templates -feature_file /acebuilds/ACE_wrappers-repository/local.features -noreldefs -type automake -exclude build,Kokyu
+
+ACE_BUILDDIR = $(top_builddir)
+ACE_ROOT = $(top_srcdir)
+
+## Makefile.ASX_CCM_App_Lib.am
+
+noinst_LTLIBRARIES = libccm_app.la
+
+libccm_app_la_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+libccm_app_la_SOURCES = \
+ CCM_App.cpp
+
+## Makefile.ASX_CCM_App_Server.am
+noinst_PROGRAMS = server
+
+server_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+server_SOURCES = \
+ SC_Server.cpp
+
+server_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Makefile.ASX_CCM_App_Client.am
+noinst_PROGRAMS += client
+
+client_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+client_SOURCES = \
+ SC_Client.cpp
+
+client_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Clean up template repositories, etc.
+clean-local:
+ -rm -f *~ *.bak *.rpo *.sym lib*.*_pure_* core core.*
+ -rm -f gcctemp.c gcctemp so_locations *.ics
+ -rm -rf cxx_repository ptrepository ti_files
+ -rm -rf templateregistry ir.out
+ -rm -rf ptrepository SunWS_cache Templates.DB
diff --git a/ACE/examples/ASX/CCM_App/SC_Client.cpp b/ACE/examples/ASX/CCM_App/SC_Client.cpp
new file mode 100644
index 00000000000..fbd4439784a
--- /dev/null
+++ b/ACE/examples/ASX/CCM_App/SC_Client.cpp
@@ -0,0 +1,13 @@
+// $Id$
+
+#include "ace/ACE.h"
+
+ACE_RCSID(CCM_App, SC_Client, "$Id$")
+
+// Pretty simple, eh? ;-)
+
+int
+ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ return 0;
+}
diff --git a/ACE/examples/ASX/CCM_App/SC_Server.cpp b/ACE/examples/ASX/CCM_App/SC_Server.cpp
new file mode 100644
index 00000000000..b93e49005bf
--- /dev/null
+++ b/ACE/examples/ASX/CCM_App/SC_Server.cpp
@@ -0,0 +1,86 @@
+// $Id$
+
+// Simple driver program for the server. This driver dynamically
+// links in all the services in the <svc.conf> file.
+
+#include "ace/OS_NS_unistd.h"
+#include "ace/OS_main.h"
+#include "ace/Service_Config.h"
+#include "ace/Thread_Manager.h"
+#include "ace/Reactor.h"
+#include "ace/Sig_Adapter.h"
+
+ACE_RCSID(CCM_App, SC_Server, "$Id$")
+
+class Event_Handler : public ACE_Event_Handler
+{
+public:
+ virtual int handle_input (ACE_HANDLE handle);
+ virtual int handle_close (ACE_HANDLE,
+ ACE_Reactor_Mask);
+};
+
+int
+Event_Handler::handle_input (ACE_HANDLE handle)
+{
+ char buf[BUFSIZ];
+ ssize_t n = ACE_OS::read (handle, buf, sizeof buf);
+
+ if (n == -1)
+ return -1;
+ else if (n == 0)
+ ACE_ERROR_RETURN ((LM_DEBUG,
+ ACE_TEXT ("shutting down on EOF\n")),
+ -1);
+ else if (ACE_OS::write (ACE_STDOUT, buf, n) != n)
+ ACE_ERROR_RETURN ((LM_DEBUG,
+ ACE_TEXT ("%p\n"), ACE_TEXT ("write failed")),
+ -1);
+ else
+ return 0;
+}
+
+int
+Event_Handler::handle_close (ACE_HANDLE, ACE_Reactor_Mask)
+{
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("closing Event_Handler\n")));
+ ACE_Reactor::instance ()->end_reactor_event_loop ();
+ return 0;
+}
+
+int
+ACE_TMAIN (int argc, ACE_TCHAR *argv[])
+{
+ ACE_Service_Config loggerd;
+ Event_Handler handler;
+ ACE_Sig_Adapter shutdown_handler ((ACE_Sig_Handler_Ex) ACE_Reactor::end_event_loop);
+
+ if (ACE_Event_Handler::register_stdin_handler (&handler,
+ ACE_Reactor::instance (),
+ ACE_Thread_Manager::instance ()) == -1)
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("register_stdin_handler")));
+
+ if (loggerd.open (argc,
+ argv,
+ ACE_DEFAULT_LOGGER_KEY,
+ // Don't ignore static services!
+ 0) == -1 && errno != ENOENT)
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("%p\n%a"),
+ ACE_TEXT ("open"),
+ 1));
+ else if (ACE_Reactor::instance ()->register_handler
+ (SIGINT, &shutdown_handler) == -1)
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("%p\n%a"),
+ ACE_TEXT ("register_handler"),
+ 1));
+
+ // Perform logging service until we receive SIGINT.
+
+ ACE_Reactor::instance ()->run_reactor_event_loop ();
+ return 0;
+}
diff --git a/ACE/examples/ASX/CCM_App/svc.conf b/ACE/examples/ASX/CCM_App/svc.conf
new file mode 100644
index 00000000000..b894e6e69e5
--- /dev/null
+++ b/ACE/examples/ASX/CCM_App/svc.conf
@@ -0,0 +1,21 @@
+static ACE_Service_Manager "-d -p 4911"
+
+dynamic Test_Task Service_Object *CCM_App:_make_Test_Task() "-p 3000"
+
+stream dynamic CCM_App STREAM *CCM_App:make_stream() active
+{
+ dynamic Device_Adapter Module *CCM_App:make_da()
+ dynamic Event_Analyzer Module *CCM_App:make_ea()
+ dynamic Multicast_Router Module *CCM_App:make_mr() "-p 3001"
+}
+
+stream CCM_App
+{
+ remove Device_Adapter
+# remove Event_Analyzer
+# remove Multicast_Router
+}
+
+# remove CCM_App
+remove Test_Task
+
diff --git a/ACE/examples/ASX/CCM_App/svc.conf.xml b/ACE/examples/ASX/CCM_App/svc.conf.xml
new file mode 100644
index 00000000000..e743d4ed986
--- /dev/null
+++ b/ACE/examples/ASX/CCM_App/svc.conf.xml
@@ -0,0 +1,33 @@
+<?xml version='1.0'?>
+<!-- Converted from svc.conf by svcconf-convert.pl -->
+<ACE_Svc_Conf>
+ <static id="ACE_Service_Manager" params="-d -p 4911"/>
+ <dynamic id="Test_Task" type="Service_Object">
+ <initializer path="CCM_App" init="_make_Test_Task" params="-p 3000"/>
+ </dynamic>
+ <streamdef>
+ <dynamic id="CCM_App" type="STREAM">
+ <initializer path="CCM_App" init="make_stream"/>
+ </dynamic>
+ <module>
+ <dynamic id="Device_Adapter" type="Module">
+ <initializer path="CCM_App" init="make_da"/>
+ </dynamic>
+ <dynamic id="Event_Analyzer" type="Module">
+ <initializer path="CCM_App" init="make_ea"/>
+ </dynamic>
+ <dynamic id="Multicast_Router" type="Module">
+ <initializer path="CCM_App" init="make_mr" params="-p 3001"/>
+ </dynamic>
+ </module>
+ </streamdef>
+ <stream id="CCM_App">
+ <module>
+ <remove id="Device_Adapter"/>
+ <!-- remove Event_Analyzer -->
+ <!-- remove Multicast_Router -->
+ </module>
+ </stream>
+ <!-- remove CCM_App -->
+ <remove id="Test_Task"/>
+</ACE_Svc_Conf>
diff --git a/ACE/examples/ASX/Event_Server/Event_Server/Consumer_Router.cpp b/ACE/examples/ASX/Event_Server/Event_Server/Consumer_Router.cpp
new file mode 100644
index 00000000000..d5215ffcd26
--- /dev/null
+++ b/ACE/examples/ASX/Event_Server/Event_Server/Consumer_Router.cpp
@@ -0,0 +1,159 @@
+// $Id$
+
+#include "ace/os_include/os_assert.h"
+#include "ace/OS_NS_stdio.h"
+#include "ace/OS_NS_string.h"
+#include "Consumer_Router.h"
+#include "Options.h"
+
+ACE_RCSID(Event_Server, Consumer_Router, "$Id$")
+
+Consumer_Router::Consumer_Router (Peer_Router_Context *prc)
+ : Peer_Router (prc)
+{
+ this->context ()->duplicate ();
+}
+
+// Initialize the Router.
+
+int
+Consumer_Router::open (void *)
+{
+ if (this->is_writer ())
+ {
+ // Set the <Peer_Router_Context> to point back to us so that if
+ // any Consumer's "accidentally" send us data we'll be able to
+ // handle it by passing it down the stream.
+ this->context ()->peer_router (this);
+
+ // Increment the reference count.
+ this->context ()->duplicate ();
+
+ // Make this an active object to handle the error cases in a
+ // separate thread. This is mostly just for illustration, i.e.,
+ // it's probably overkill to use a thread for this!
+ return this->activate (Options::instance ()->t_flags ());
+ }
+ else // if (this->is_reader ())
+
+ // Nothing to do since this side is primarily used to transmit to
+ // Consumers, rather than receive.
+ return 0;
+}
+
+int
+Consumer_Router::close (u_long)
+{
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("(%t) closing Consumer_Router %s\n"),
+ this->is_reader () ? ACE_TEXT ("reader") : ACE_TEXT ("writer")));
+
+ if (this->is_writer ())
+ // Inform the thread to shut down.
+ this->msg_queue ()->deactivate ();
+
+ // Both writer and reader call <release>, so the context knows when
+ // to clean itself up.
+ this->context ()->release ();
+ return 0;
+}
+
+// Handle incoming messages in a separate thread.
+
+int
+Consumer_Router::svc (void)
+{
+ assert (this->is_writer ());
+
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("(%t) starting svc in Consumer_Router\n")));
+
+ for (ACE_Message_Block *mb = 0;
+ this->getq (mb) >= 0;
+ )
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("(%t) warning: Consumer_Router is ")
+ ACE_TEXT ("forwarding a message to Supplier_Router\n")));
+
+ // Pass this message down to the next Module's writer Task.
+ if (this->put_next (mb) == -1)
+ ACE_ERROR_RETURN
+ ((LM_ERROR,
+ ACE_TEXT ("(%t) send_peers failed in Consumer_Router\n")),
+ -1);
+ }
+
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("(%t) stopping svc in Consumer_Router\n")));
+ return 0;
+ // Note the implicit ACE_OS::thr_exit() via destructor.
+}
+
+// Send a <Message_Block> to the supplier(s).
+
+int
+Consumer_Router::put (ACE_Message_Block *mb,
+ ACE_Time_Value *)
+{
+ // Perform the necessary control operations before passing the
+ // message down the stream.
+
+ if (mb->msg_type () == ACE_Message_Block::MB_IOCTL)
+ {
+ this->control (mb);
+ return this->put_next (mb);
+ }
+
+ // If we're the reader then we're responsible for broadcasting
+ // messages to Consumers.
+
+ else if (this->is_reader ())
+ {
+ if (this->context ()->send_peers (mb) == -1)
+ ACE_ERROR_RETURN
+ ((LM_ERROR,
+ ACE_TEXT ("(%t) send_peers failed in Consumer_Router\n")),
+ -1);
+ else
+ return 0;
+ }
+ else // if (this->is_writer ())
+
+ // Queue up the message to processed by <Consumer_Router::svc>
+ // Since we don't expect to be getting many of these messages, we
+ // queue them up and run them in a separate thread to avoid taxing
+ // the main thread.
+ return this->putq (mb);
+}
+
+// Return information about the <Consumer_Router>.
+#if defined (ACE_WIN32) || !defined (ACE_USES_WCHAR)
+# define FMTSTR ACE_TEXT ("%s\t %d/%s %s (%s)\n")
+#else
+# define FMTSTR ACE_TEXT ("%ls\t %d/%ls %ls (%ls)\n")
+#endif /* ACE_WIN32 || !ACE_USES_WCHAR */
+
+int
+Consumer_Router::info (ACE_TCHAR **strp, size_t length) const
+{
+ ACE_TCHAR buf[BUFSIZ];
+ ACE_INET_Addr addr;
+ const ACE_TCHAR *mod_name = this->name ();
+
+ if (this->context ()->acceptor ().get_local_addr (addr) == -1)
+ return -1;
+
+ ACE_OS::sprintf (buf,
+ FMTSTR,
+ mod_name,
+ addr.get_port_number (),
+ ACE_TEXT ("tcp"),
+ ACE_TEXT ("# consumer router"),
+ this->is_reader () ? ACE_TEXT ("reader") : ACE_TEXT ("writer"));
+ if (*strp == 0 && (*strp = ACE_OS::strdup (mod_name)) == 0)
+ return -1;
+ else
+ ACE_OS::strncpy (*strp, mod_name, length);
+
+ return ACE_OS::strlen (mod_name);
+}
diff --git a/ACE/examples/ASX/Event_Server/Event_Server/Consumer_Router.h b/ACE/examples/ASX/Event_Server/Event_Server/Consumer_Router.h
new file mode 100644
index 00000000000..062a07116ea
--- /dev/null
+++ b/ACE/examples/ASX/Event_Server/Event_Server/Consumer_Router.h
@@ -0,0 +1,71 @@
+/* -*- C++ -*- */
+// $Id$
+
+#ifndef _CONSUMER_ROUTER_H
+#define _CONSUMER_ROUTER_H
+
+#include "ace/SOCK_Acceptor.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/UPIPE_Acceptor.h"
+#include "ace/Svc_Handler.h"
+#include "ace/RW_Thread_Mutex.h"
+#include "Peer_Router.h"
+
+class Consumer_Router : public Peer_Router
+{
+ // = TITLE
+ // Provides the interface between one or more Consumers and the
+ // Event Server <ACE_Stream>.
+ //
+ // = DESCRIPTION
+ // This class normally sits on "top" of the Stream and routes
+ // messages coming from "downstream" to all the Consumers
+ // connected to it via its "read" <Task>. Normally, the messages
+ // flow up the stream from <Supplier_Router>s. However, if
+ // Consumers transmit data to the <Consumer_Router>, we dutifully
+ // push it out to the Suppliers via the <Supplier_Router>.
+ //
+ // When used on the "reader" side of a Stream, the
+ // <Consumer_Router> simply forwards all messages up the stream.
+ // When used on the "writer" side, the <Consumer_Router> queues
+ // up outgoing messages to suppliers and sends them down to the
+ // <Supplier_Router> in a separate thread. The reason for this
+ // is that it's really an "error" for a <Consumer_Router> to
+ // send messages to Suppliers, so we don't expect this to happen
+ // very much. When it does we use a separate thread to avoid
+ // taxing the main thread, which processes "normal" messages.
+ //
+ // All of the methods in this class except the constructor are
+ // called via base class pointers by the <ACE_Stream>.
+ // Therefore, we can put them in the protected section.
+public:
+ Consumer_Router (Peer_Router_Context *prc);
+ // Initialization method.
+
+protected:
+ // = ACE_Task hooks.
+ virtual int open (void *a = 0);
+ // Called by the Stream to initialize the router.
+
+ virtual int close (u_long flags = 0);
+ // Called by the Stream to shutdown the router.
+
+ virtual int put (ACE_Message_Block *msg, ACE_Time_Value * = 0);
+ // Called by the <Peer_Handler> to pass a message to the
+ // <Consumer_Router>. The <Consumer_Router> queues up this message,
+ // which is then processed in the <svc> method in a separate thread.
+
+ virtual int svc (void);
+ // Runs in a separate thread to dequeue messages and pass them up
+ // the stream.
+
+ // = Dynamic linking hooks.
+ virtual int info (ACE_TCHAR **info_string, size_t length) const;
+ // Returns information about this service.
+};
+
+#endif /* _CONSUMER_ROUTER_H */
diff --git a/ACE/examples/ASX/Event_Server/Event_Server/Event.mpc b/ACE/examples/ASX/Event_Server/Event_Server/Event.mpc
new file mode 100644
index 00000000000..f99e912ce04
--- /dev/null
+++ b/ACE/examples/ASX/Event_Server/Event_Server/Event.mpc
@@ -0,0 +1,15 @@
+// -*- MPC -*-
+// $Id$
+
+project(*Server) : aceexe {
+ avoids += ace_for_tao
+ exename = Event_Server
+ Source_Files {
+ Consumer_Router.cpp
+ Event_Analyzer.cpp
+ Options.cpp
+ Peer_Router.cpp
+ Supplier_Router.cpp
+ event_server.cpp
+ }
+}
diff --git a/ACE/examples/ASX/Event_Server/Event_Server/Event_Analyzer.cpp b/ACE/examples/ASX/Event_Server/Event_Server/Event_Analyzer.cpp
new file mode 100644
index 00000000000..a064da6459a
--- /dev/null
+++ b/ACE/examples/ASX/Event_Server/Event_Server/Event_Analyzer.cpp
@@ -0,0 +1,80 @@
+// $Id$
+
+#include "ace/OS_NS_string.h"
+#include "Options.h"
+#include "Event_Analyzer.h"
+
+ACE_RCSID(Event_Server, Event_Analyzer, "$Id$")
+
+int
+Event_Analyzer::open (void *)
+{
+ // No-op for now...
+ return 0;
+}
+
+int
+Event_Analyzer::close (u_long)
+{
+ // No-op for now...
+ return 0;
+}
+
+int
+Event_Analyzer::control (ACE_Message_Block *mb)
+{
+ ACE_IO_Cntl_Msg *ioc = (ACE_IO_Cntl_Msg *) mb->rd_ptr ();
+ ACE_IO_Cntl_Msg::ACE_IO_Cntl_Cmds cmd;
+
+ switch (cmd = ioc->cmd ())
+ {
+ case ACE_IO_Cntl_Msg::SET_LWM:
+ case ACE_IO_Cntl_Msg::SET_HWM:
+ this->water_marks (cmd, *(size_t *) mb->cont ()->rd_ptr ());
+ break;
+ default:
+ break;
+ }
+ return 0;
+}
+
+int
+Event_Analyzer::put (ACE_Message_Block *mb, ACE_Time_Value *)
+{
+ if (Options::instance ()->debug ())
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("(%t) passing through Event_Analyser::put() (%s)\n"),
+ this->is_reader () ? ACE_TEXT ("reader") : ACE_TEXT ("writer")));
+
+ if (mb->msg_type () == ACE_Message_Block::MB_IOCTL)
+ this->control (mb);
+
+ // Just pass the message along to the next Module in the stream...
+ return this->put_next (mb);
+}
+
+int
+Event_Analyzer::init (int, ACE_TCHAR *[])
+{
+ // No-op for now.
+ return 0;
+}
+
+int
+Event_Analyzer::fini (void)
+{
+ // No-op for now.
+ return 0;
+}
+
+int
+Event_Analyzer::info (ACE_TCHAR **strp, size_t length) const
+{
+ const ACE_TCHAR *mod_name = this->name ();
+
+ if (*strp == 0 && (*strp = ACE_OS::strdup (mod_name)) == 0)
+ return -1;
+ else
+ ACE_OS::strncpy (*strp, mod_name, length);
+ return ACE_OS::strlen (mod_name);
+}
diff --git a/ACE/examples/ASX/Event_Server/Event_Server/Event_Analyzer.h b/ACE/examples/ASX/Event_Server/Event_Server/Event_Analyzer.h
new file mode 100644
index 00000000000..d4f88c8b68d
--- /dev/null
+++ b/ACE/examples/ASX/Event_Server/Event_Server/Event_Analyzer.h
@@ -0,0 +1,44 @@
+/* -*- C++ -*- */
+// $Id$
+
+#ifndef _EVENT_ANALYZER_H
+#define _EVENT_ANALYZER_H
+
+#include "ace/Stream.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/Module.h"
+#include "ace/Task.h"
+
+class Event_Analyzer : public ACE_Task<ACE_SYNCH>
+{
+ // = TITLE
+ // This class forwards all the <ACE_Message_Block>s it receives
+ // onto its neighboring Module in the Stream.
+ //
+ // = DESCRIPTION
+ // In a "real" event service, application-specific processing
+ // would be done in the <put> (or <svc>) method in this class.
+public:
+ // = Initialization hooks called by <ACE_Stream> (not used).
+ virtual int open (void *a = 0);
+ virtual int close (u_long flags = 0);
+
+ virtual int put (ACE_Message_Block *msg,
+ ACE_Time_Value * = 0);
+ // Entry point into this task.
+
+ // Dynamic linking hooks (not used).
+ virtual int init (int argc, ACE_TCHAR *argv[]);
+ virtual int fini (void);
+ virtual int info (ACE_TCHAR **info_string,
+ size_t length) const;
+private:
+ virtual int control (ACE_Message_Block *);
+ // Implements the watermark control processing.
+};
+
+#endif /* _EVENT_ANALYZER_H */
diff --git a/ACE/examples/ASX/Event_Server/Event_Server/Makefile.am b/ACE/examples/ASX/Event_Server/Event_Server/Makefile.am
new file mode 100644
index 00000000000..5e17126f991
--- /dev/null
+++ b/ACE/examples/ASX/Event_Server/Event_Server/Makefile.am
@@ -0,0 +1,49 @@
+## Process this file with automake to create Makefile.in
+##
+## $Id$
+##
+## This file was generated by MPC. Any changes made directly to
+## this file will be lost the next time it is generated.
+##
+## MPC Command:
+## /acebuilds/ACE_wrappers-repository/bin/mwc.pl -include /acebuilds/MPC/config -include /acebuilds/MPC/templates -feature_file /acebuilds/ACE_wrappers-repository/local.features -noreldefs -type automake -exclude build,Kokyu
+
+ACE_BUILDDIR = $(top_builddir)
+ACE_ROOT = $(top_srcdir)
+
+
+## Makefile.Event_Server.am
+
+if !BUILD_ACE_FOR_TAO
+noinst_PROGRAMS = Event_Server
+
+Event_Server_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+Event_Server_SOURCES = \
+ Consumer_Router.cpp \
+ Event_Analyzer.cpp \
+ Options.cpp \
+ Peer_Router.cpp \
+ Supplier_Router.cpp \
+ event_server.cpp \
+ Consumer_Router.h \
+ Event_Analyzer.h \
+ Options.h \
+ Options.i \
+ Peer_Router.h \
+ Supplier_Router.h
+
+Event_Server_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+endif !BUILD_ACE_FOR_TAO
+
+## Clean up template repositories, etc.
+clean-local:
+ -rm -f *~ *.bak *.rpo *.sym lib*.*_pure_* core core.*
+ -rm -f gcctemp.c gcctemp so_locations *.ics
+ -rm -rf cxx_repository ptrepository ti_files
+ -rm -rf templateregistry ir.out
+ -rm -rf ptrepository SunWS_cache Templates.DB
diff --git a/ACE/examples/ASX/Event_Server/Event_Server/Options.cpp b/ACE/examples/ASX/Event_Server/Event_Server/Options.cpp
new file mode 100644
index 00000000000..6ef846f2f31
--- /dev/null
+++ b/ACE/examples/ASX/Event_Server/Event_Server/Options.cpp
@@ -0,0 +1,206 @@
+// $Id$
+
+#include "ace/Get_Opt.h"
+#include "ace/Thread.h"
+#include "ace/Log_Msg.h"
+#include "ace/OS_NS_stdio.h"
+#if defined (ACE_HAS_TRACE)
+# include "ace/OS_NS_strings.h"
+#endif /* ACE_HAS_TRACE */
+
+#include "Options.h"
+
+ACE_RCSID(Event_Server, Options, "$Id$")
+
+/* static */
+Options *Options::instance_ = 0;
+
+Options *
+Options::instance (void)
+{
+ if (Options::instance_ == 0)
+ Options::instance_ = new Options;
+
+ return Options::instance_;
+}
+
+Options::Options (void)
+ : thr_count_ (4),
+ t_flags_ (0),
+ high_water_mark_ (8 * 1024),
+ low_water_mark_ (1024),
+ message_size_ (128),
+ initial_queue_length_ (0),
+ iterations_ (100000),
+ debugging_ (0),
+ verbosity_ (0),
+ consumer_port_ (ACE_DEFAULT_SERVER_PORT),
+ supplier_port_ (ACE_DEFAULT_SERVER_PORT + 1)
+{
+}
+
+Options::~Options (void)
+{
+}
+
+void Options::print_results (void)
+{
+#if !defined (ACE_WIN32)
+ ACE_Profile_Timer::ACE_Elapsed_Time et;
+
+ this->itimer_.elapsed_time (et);
+
+ if (this->verbose ())
+ {
+#if defined (ACE_HAS_PRUSAGE_T)
+ ACE_Profile_Timer::Rusage rusage;
+ this->itimer_.get_rusage (rusage);
+
+ ACE_OS::printf ("final concurrency hint = %d\n", ACE_Thread::getconcurrency ());
+ ACE_OS::printf ("%8d = lwpid\n"
+ "%8d = lwp count\n"
+ "%8d = minor page faults\n"
+ "%8d = major page faults\n"
+ "%8d = input blocks\n"
+ "%8d = output blocks\n"
+ "%8d = messages sent\n"
+ "%8d = messages received\n"
+ "%8d = signals received\n"
+ "%8ds, %dms = wait-cpu (latency) time\n"
+ "%8ds, %dms = user lock wait sleep time\n"
+ "%8ds, %dms = all other sleep time\n"
+ "%8d = voluntary context switches\n"
+ "%8d = involuntary context switches\n"
+ "%8d = system calls\n"
+ "%8d = chars read/written\n",
+ (int) rusage.pr_lwpid,
+ (int) rusage.pr_count,
+ (int) rusage.pr_minf,
+ (int) rusage.pr_majf,
+ (int) rusage.pr_inblk,
+ (int) rusage.pr_oublk,
+ (int) rusage.pr_msnd,
+ (int) rusage.pr_mrcv,
+ (int) rusage.pr_sigs,
+ (int) rusage.pr_wtime.tv_sec, (int) rusage.pr_wtime.tv_nsec / 1000000,
+ (int) rusage.pr_ltime.tv_sec, (int) rusage.pr_ltime.tv_nsec / 1000000,
+ (int) rusage.pr_slptime.tv_sec, (int) rusage.pr_slptime.tv_nsec / 1000000,
+ (int) rusage.pr_vctx,
+ (int) rusage.pr_ictx,
+ (int) rusage.pr_sysc,
+ (int) rusage.pr_ioch);
+#else
+ /* Someone needs to write the corresponding dump for rusage... */
+#endif /* ACE_HAS_PRUSAGE_T */
+ }
+
+ ACE_OS::printf ("---------------------\n"
+ "real time = %.3f\n"
+ "user time = %.3f\n"
+ "system time = %.3f\n"
+ "---------------------\n",
+ et.real_time, et.user_time, et.system_time);
+#endif /* ACE_WIN32 */
+}
+
+void
+Options::parse_args (int argc, ACE_TCHAR *argv[])
+{
+ ACE_LOG_MSG->open (argv[0]);
+
+ ACE_Get_Opt get_opt (argc, argv, ACE_TEXT ("c:bdH:i:L:l:M:ns:t:T:v"));
+ int c;
+
+ while ((c = get_opt ()) != EOF)
+ switch (c)
+ {
+ case 'b':
+ this->t_flags (THR_BOUND);
+ break;
+ case 'c':
+ this->consumer_port (ACE_OS::atoi (get_opt.opt_arg ()));
+ break;
+ case 'd':
+ this->debugging_ = 1;
+ break;
+ case 'H':
+ this->high_water_mark (ACE_OS::atoi (get_opt.opt_arg ()));
+ break;
+ case 'i':
+ this->iterations (ACE_OS::atoi (get_opt.opt_arg ()));
+ break;
+ case 'L':
+ this->low_water_mark (ACE_OS::atoi (get_opt.opt_arg ()));
+ break;
+ case 'l':
+ this->initial_queue_length (ACE_OS::atoi (get_opt.opt_arg ()));
+ break;
+ case 'M':
+ this->message_size (ACE_OS::atoi (get_opt.opt_arg ()));
+ break;
+ case 'n':
+ this->t_flags (THR_NEW_LWP);
+ break;
+ case 's':
+ this->supplier_port (ACE_OS::atoi (get_opt.opt_arg ()));
+ break;
+ case 'T':
+#if defined (ACE_HAS_TRACE)
+ if (ACE_OS::strcasecmp (get_opt.opt_arg (), ACE_TEXT ("ON")) == 0)
+ ACE_Trace::start_tracing ();
+ else if (ACE_OS::strcasecmp (get_opt.opt_arg (), ACE_TEXT ("OFF")) == 0)
+ ACE_Trace::stop_tracing ();
+#endif /* ACE_HAS_TRACE */
+ break;
+ case 't':
+ this->thr_count (ACE_OS::atoi (get_opt.opt_arg ()));
+ break;
+ case 'v':
+ this->verbosity_ = 1;
+ break;
+ default:
+ ::fprintf (stderr, "%s\n"
+ "\t[-b] (THR_BOUND)\n"
+ "\t[-c consumer port]\n"
+ "\t[-d] (enable debugging)\n"
+ "\t[-H high water mark]\n"
+ "\t[-i number of test iterations]\n"
+ "\t[-L low water mark]\n"
+ "\t[-M] message size \n"
+ "\t[-n] (THR_NEW_LWP)\n"
+ "\t[-q max queue size]\n"
+ "\t[-s supplier port]\n"
+ "\t[-t number of threads]\n"
+ "\t[-v] (verbose) \n",
+ ACE_TEXT_ALWAYS_CHAR (argv[0]));
+ ::exit (1);
+ /* NOTREACHED */
+ break;
+ }
+
+ // This is a major hack to get the size_t format spec to be a narrow
+ // char, same as the other strings for printf() here. It only works
+ // because this is the end of the source file. It makes the
+ // ACE_SIZE_T_FORMAT_SPECIFIER not use ACE_LIB_TEXT, effectively.
+#undef ACE_LIB_TEXT
+#define ACE_LIB_TEXT(A) A
+ if (this->verbose ())
+ ACE_OS::printf ("%8d = initial concurrency hint\n"
+ ACE_SIZE_T_FORMAT_SPECIFIER " = total iterations\n"
+ ACE_SIZE_T_FORMAT_SPECIFIER " = thread count\n"
+ ACE_SIZE_T_FORMAT_SPECIFIER " = low water mark\n"
+ ACE_SIZE_T_FORMAT_SPECIFIER " = high water mark\n"
+ ACE_SIZE_T_FORMAT_SPECIFIER " = message_size\n"
+ ACE_SIZE_T_FORMAT_SPECIFIER " = initial queue length\n"
+ "%8d = THR_BOUND\n"
+ "%8d = THR_NEW_LWP\n",
+ ACE_Thread::getconcurrency (),
+ this->iterations (),
+ this->thr_count (),
+ this->low_water_mark (),
+ this->high_water_mark (),
+ this->message_size (),
+ this->initial_queue_length (),
+ (this->t_flags () & THR_BOUND) != 0,
+ (this->t_flags () & THR_NEW_LWP) != 0);
+}
diff --git a/ACE/examples/ASX/Event_Server/Event_Server/Options.h b/ACE/examples/ASX/Event_Server/Event_Server/Options.h
new file mode 100644
index 00000000000..96e2cad3627
--- /dev/null
+++ b/ACE/examples/ASX/Event_Server/Event_Server/Options.h
@@ -0,0 +1,122 @@
+/* -*- C++ -*- */
+// $Id$
+
+#ifndef OPTIONS_H
+#define OPTIONS_H
+
+#include "ace/config-all.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/Profile_Timer.h"
+
+class Options
+{
+ // = TITLE
+ // Option Singleton for Event Server.
+public:
+ static Options *instance (void);
+ // Singleton access point.
+
+ void parse_args (int argc, ACE_TCHAR *argv[]);
+ // Parse the command-line arguments and set the options.
+
+ // = Timer management.
+ void stop_timer (void);
+ void start_timer (void);
+
+ // = Set/get the number of threads.
+ void thr_count (size_t count);
+ size_t thr_count (void);
+
+ // = Set/get the size of the queue.
+ void initial_queue_length (size_t length);
+ size_t initial_queue_length (void);
+
+ // = Set/get the high water mark.
+ void high_water_mark (size_t size);
+ size_t high_water_mark (void);
+
+ // = Set/get the high water mark.
+ void low_water_mark (size_t size);
+ size_t low_water_mark (void);
+
+ // = Set/get the size of a message.
+ void message_size (size_t size);
+ size_t message_size (void);
+
+ // = Set/get the number of iterations.
+ void iterations (size_t n);
+ size_t iterations (void);
+
+ // Set/get threading flags.
+ void t_flags (long flag);
+ long t_flags (void);
+
+ // Set/get supplier port number.
+ void supplier_port (u_short port);
+ u_short supplier_port (void);
+
+ // Set/get consumer port number.
+ void consumer_port (u_short port);
+ u_short consumer_port (void);
+
+ // Enabled if we're in debugging mode.
+ int debug (void);
+
+ // Enabled if we're in verbose mode.
+ int verbose (void);
+
+ // Print the results to the STDERR.
+ void print_results (void);
+
+private:
+ // = Ensure we're a Singleton.
+ Options (void);
+ ~Options (void);
+
+ ACE_Profile_Timer itimer_;
+ // Time the process.
+
+ size_t thr_count_;
+ // Number of threads to spawn.
+
+ long t_flags_;
+ // Flags to <thr_create>.
+
+ size_t high_water_mark_;
+ // ACE_Task high water mark.
+
+ size_t low_water_mark_;
+ // ACE_Task low water mark.
+
+ size_t message_size_;
+ // Size of a message.
+
+ size_t initial_queue_length_;
+ // Initial number of items in the queue.
+
+ size_t iterations_;
+ // Number of iterations to run the test program.
+
+ int debugging_;
+ // Extra debugging info.
+
+ int verbosity_;
+ // Extra verbose messages.
+
+ u_short consumer_port_;
+ // Port that the Consumer_Router is using.
+
+ u_short supplier_port_;
+ // Port that the Supplier_Router is using.
+
+ static Options *instance_;
+ // Static Singleton.
+
+};
+
+#include "Options.i"
+#endif /* OPTIONS_H */
diff --git a/ACE/examples/ASX/Event_Server/Event_Server/Options.i b/ACE/examples/ASX/Event_Server/Event_Server/Options.i
new file mode 100644
index 00000000000..87ff395c503
--- /dev/null
+++ b/ACE/examples/ASX/Event_Server/Event_Server/Options.i
@@ -0,0 +1,141 @@
+/* -*- C++ -*- */
+// $Id$
+
+/* Option manager for ustreams */
+
+// Since this is only included in Options.h these should stay
+// inline, not ACE_INLINE.
+// FUZZ: disable check_for_inline
+
+inline void
+Options::supplier_port (u_short port)
+{
+ this->supplier_port_ = port;
+}
+
+inline u_short
+Options::supplier_port (void)
+{
+ return this->supplier_port_;
+}
+
+inline void
+Options::consumer_port (u_short port)
+{
+ this->consumer_port_ = port;
+}
+
+inline u_short
+Options::consumer_port (void)
+{
+ return this->consumer_port_;
+}
+
+inline void
+Options::start_timer (void)
+{
+ this->itimer_.start ();
+}
+
+inline void
+Options::stop_timer (void)
+{
+ this->itimer_.stop ();
+}
+
+inline void
+Options::thr_count (size_t count)
+{
+ this->thr_count_ = count;
+}
+
+inline size_t
+Options::thr_count (void)
+{
+ return this->thr_count_;
+}
+
+inline void
+Options::initial_queue_length (size_t length)
+{
+ this->initial_queue_length_ = length;
+}
+
+inline size_t
+Options::initial_queue_length (void)
+{
+ return this->initial_queue_length_;
+}
+
+inline void
+Options::high_water_mark (size_t size)
+{
+ this->high_water_mark_ = size;
+}
+
+inline size_t
+Options::high_water_mark (void)
+{
+ return this->high_water_mark_;
+}
+
+inline void
+Options::low_water_mark (size_t size)
+{
+ this->low_water_mark_ = size;
+}
+
+inline size_t
+Options::low_water_mark (void)
+{
+ return this->low_water_mark_;
+}
+
+inline void
+Options::message_size (size_t size)
+{
+ this->message_size_ = size;
+}
+
+inline size_t
+Options::message_size (void)
+{
+ return this->message_size_;
+}
+
+inline void
+Options::iterations (size_t n)
+{
+ this->iterations_ = n;
+}
+
+inline size_t
+Options::iterations (void)
+{
+ return this->iterations_;
+}
+
+inline void
+Options::t_flags (long flag)
+{
+ this->t_flags_ |= flag;
+}
+
+inline long
+Options::t_flags (void)
+{
+ return this->t_flags_;
+}
+
+inline int
+Options::debug (void)
+{
+ return this->debugging_;
+}
+
+inline int
+Options::verbose (void)
+{
+ return this->verbosity_;
+}
+
diff --git a/ACE/examples/ASX/Event_Server/Event_Server/Peer_Router.cpp b/ACE/examples/ASX/Event_Server/Event_Server/Peer_Router.cpp
new file mode 100644
index 00000000000..cb82eec16df
--- /dev/null
+++ b/ACE/examples/ASX/Event_Server/Event_Server/Peer_Router.cpp
@@ -0,0 +1,435 @@
+// $Id$
+
+#if !defined (_PEER_ROUTER_C)
+#define _PEER_ROUTER_C
+
+#include "ace/Service_Config.h"
+#include "ace/Get_Opt.h"
+#include "Options.h"
+#include "Peer_Router.h"
+
+ACE_RCSID(Event_Server, Peer_Router, "$Id$")
+
+// Send the <ACE_Message_Block> to all the peers. Note that in a
+// "real" application this logic would most likely be more selective,
+// i.e., it would actually do "routing" based on addressing
+// information passed in the <ACE_Message_Block>.
+
+int
+Peer_Router_Context::send_peers (ACE_Message_Block *mb)
+{
+ PEER_ITERATOR map_iter = this->peer_map_;
+ int bytes = 0;
+ int iterations = 0;
+
+ // Skip past the header and get the message to send.
+ ACE_Message_Block *data_block = mb->cont ();
+
+ // Use an iterator to "multicast" the data to *all* the registered
+ // peers. Note that this doesn't really multicast, it just makes a
+ // "logical" copy of the <ACE_Message_Block> and enqueues it in the
+ // appropriate <Peer_Handler> corresponding to each peer. Note that
+ // a "real" application would probably "route" the data to a subset
+ // of connected peers here, rather than send it to all the peers.
+
+ for (PEER_ENTRY *ss = 0;
+ map_iter.next (ss) != 0;
+ map_iter.advance ())
+ {
+ if (Options::instance ()->debug ())
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("(%t) sending to peer via handle %d\n"),
+ ss->ext_id_));
+
+ iterations++;
+
+ // Increment reference count before sending since the
+ // <Peer_Handler> might be running in its own thread of control.
+ bytes += ss->int_id_->put (data_block->duplicate ());
+ }
+
+ mb->release ();
+ return bytes == 0 ? 0 : bytes / iterations;
+}
+
+// Remove the <Peer_Handler> from the peer connection map.
+
+int
+Peer_Router_Context::unbind_peer (ROUTING_KEY key)
+{
+ return this->peer_map_.unbind (key);
+}
+
+// Add the <Peer_Handler> to the peer connection map.
+
+int
+Peer_Router_Context::bind_peer (ROUTING_KEY key,
+ Peer_Handler *peer_handler)
+{
+ return this->peer_map_.bind (key, peer_handler);
+}
+
+void
+Peer_Router_Context::duplicate (void)
+{
+ this->reference_count_++;
+}
+
+void
+Peer_Router_Context::release (void)
+{
+ ACE_ASSERT (this->reference_count_ > 0);
+ this->reference_count_--;
+
+ if (this->reference_count_ == 0)
+ delete this;
+}
+
+Peer_Router_Context::Peer_Router_Context (u_short port)
+ : reference_count_ (0)
+{
+ // Initialize the Acceptor's "listen-mode" socket.
+ ACE_INET_Addr endpoint (port);
+ if (this->open (endpoint) == -1)
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("Acceptor::open")));
+
+ // Initialize the connection map.
+ else if (this->peer_map_.open () == -1)
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("Map_Manager::open")));
+ else
+ {
+ ACE_INET_Addr addr;
+
+ if (this->acceptor ().get_local_addr (addr) != -1)
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("(%t) initializing %C on port = %d, handle = %d, this = %u\n"),
+ addr.get_port_number () == Options::instance ()->supplier_port ()
+ ? "Supplier_Handler" : "Consumer_Handler",
+ addr.get_port_number (),
+ this->acceptor().get_handle (),
+ this));
+ else
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("get_local_addr")));
+ }
+}
+
+Peer_Router_Context::~Peer_Router_Context (void)
+{
+ // Free up the handle and close down the listening socket.
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("(%t) closing down Peer_Router_Context\n")));
+
+ // Close down the Acceptor and take ourselves out of the Reactor.
+ this->handle_close ();
+
+ PEER_ITERATOR map_iter = this->peer_map_;
+
+ // Make sure to take all the handles out of the map to avoid
+ // "resource leaks."
+
+ for (PEER_ENTRY *ss = 0;
+ map_iter.next (ss) != 0;
+ map_iter.advance ())
+ {
+ if (Options::instance ()->debug ())
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("(%t) closing down peer on handle %d\n"),
+ ss->ext_id_));
+
+ if (ACE_Reactor::instance ()->remove_handler
+ (ss->ext_id_,
+ ACE_Event_Handler::READ_MASK) == -1)
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("(%t) p\n"),
+ ACE_TEXT ("remove_handle")));
+ }
+
+ // Close down the map.
+ this->peer_map_.close ();
+}
+
+Peer_Router *
+Peer_Router_Context::peer_router (void)
+{
+ return this->peer_router_;
+}
+
+void
+Peer_Router_Context::peer_router (Peer_Router *pr)
+{
+ this->peer_router_ = pr;
+}
+
+// Factory Method that creates a new <Peer_Handler> for each
+// connection.
+
+int
+Peer_Router_Context::make_svc_handler (Peer_Handler *&sh)
+{
+ ACE_NEW_RETURN (sh,
+ Peer_Handler (this),
+ -1);
+ return 0;
+}
+
+Peer_Handler::Peer_Handler (Peer_Router_Context *prc)
+ : peer_router_context_ (prc)
+{
+}
+
+// Send output to a peer. Note that this implementation "blocks" if
+// flow control occurs. This is undesirable for "real" applications.
+// The best way around this is to make the <Peer_Handler> an Active
+// Object, e.g., as done in the $ACE_ROOT/apps/Gateway/Gateway
+// application.
+
+int
+Peer_Handler::put (ACE_Message_Block *mb,
+ ACE_Time_Value *tv)
+{
+#if 0
+ // If we're running as Active Objects just enqueue the message here.
+ return this->putq (mb, tv);
+#else
+ ACE_UNUSED_ARG (tv);
+
+ int result = this->peer ().send_n (mb->rd_ptr (),
+ mb->length ());
+ // Release the memory.
+ mb->release ();
+
+ return result;
+#endif /* 0 */
+}
+
+// Initialize a newly connected handler.
+
+int
+Peer_Handler::open (void *)
+{
+ ACE_TCHAR buf[BUFSIZ], *p = buf;
+
+ if (this->peer_router_context_->peer_router ()->info (&p,
+ sizeof buf) != -1)
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("(%t) creating handler for %s, handle = %d\n"),
+ buf,
+ this->get_handle ()));
+ else
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("info")),
+ -1);
+#if 0
+ // If we're running as an Active Object activate the Peer_Handler
+ // here.
+ if (this->activate (Options::instance ()->t_flags ()) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("activation of thread failed")),
+ -1);
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("(%t) Peer_Handler::open registering with Reactor for handle_input\n")));
+#else
+
+ // Register with the Reactor to receive messages from our Peer.
+ if (ACE_Reactor::instance ()->register_handler
+ (this, ACE_Event_Handler::READ_MASK) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("register_handler")),
+ -1);
+#endif /* 0 */
+
+ // Insert outselves into the routing map.
+ else if (this->peer_router_context_->bind_peer (this->get_handle (),
+ this) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("bind_peer")),
+ -1);
+ else
+ return 0;
+}
+
+// Receive a message from a Peer.
+
+int
+Peer_Handler::handle_input (ACE_HANDLE h)
+{
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("(%t) input arrived on handle %d\n"),
+ h));
+
+ ACE_Message_Block *db;
+
+ ACE_NEW_RETURN (db, ACE_Message_Block (BUFSIZ), -1);
+
+ ACE_Message_Block *hb = new ACE_Message_Block (sizeof (ROUTING_KEY),
+ ACE_Message_Block::MB_PROTO, db);
+ // Check for memory failures.
+ if (hb == 0)
+ {
+ db->release ();
+ errno = ENOMEM;
+ return -1;
+ }
+
+ ssize_t n = this->peer ().recv (db->rd_ptr (),
+ db->size ());
+
+ if (n == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p"),
+ ACE_TEXT ("recv failed")),
+ -1);
+ else if (n == 0) // Client has closed down the connection.
+ {
+ if (this->peer_router_context_->unbind_peer (this->get_handle ()) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p"),
+ ACE_TEXT ("unbind failed")),
+ -1);
+
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("(%t) shutting down handle %d\n"), h));
+ // Instruct the <ACE_Reactor> to deregister us by returning -1.
+ return -1;
+ }
+ else
+ {
+ // Transform incoming buffer into an <ACE_Message_Block>.
+
+ // First, increment the write pointer to the end of the newly
+ // read data block.
+ db->wr_ptr (n);
+
+ // Second, copy the "address" into the header block. Note that
+ // for this implementation the HANDLE we receive the message on
+ // is considered the "address." A "real" application would want
+ // to do something more sophisticated.
+ *(ACE_HANDLE *) hb->rd_ptr () = this->get_handle ();
+
+ // Third, update the write pointer in the header block.
+ hb->wr_ptr (sizeof (ACE_HANDLE));
+
+ // Finally, pass the message through the stream. Note that we
+ // use <Task::put> here because this gives the method at *our*
+ // level in the stream a chance to do something with the message
+ // before it is sent up the other side. For instance, if we
+ // receive messages in the <Supplier_Router>, it will just call
+ // <put_next> and send them up the stream to the
+ // <Consumer_Router> (which broadcasts them to consumers).
+ // However, if we receive messages in the <Consumer_Router>, it
+ // could reply to the Consumer with an error since it's not
+ // correct for Consumers to send messages (we don't do this in
+ // the current implementation, but it could be done in a "real"
+ // application).
+
+ if (this->peer_router_context_->peer_router ()->put (hb) == -1)
+ return -1;
+ else
+ return 0;
+ }
+}
+
+Peer_Router::Peer_Router (Peer_Router_Context *prc)
+ : peer_router_context_ (prc)
+{
+}
+
+Peer_Router_Context *
+Peer_Router::context (void) const
+{
+ return this->peer_router_context_;
+}
+
+int
+Peer_Router::control (ACE_Message_Block *mb)
+{
+ ACE_IO_Cntl_Msg *ioc = (ACE_IO_Cntl_Msg *) mb->rd_ptr ();
+ ACE_IO_Cntl_Msg::ACE_IO_Cntl_Cmds command;
+
+ switch (command = ioc->cmd ())
+ {
+ case ACE_IO_Cntl_Msg::SET_LWM:
+ case ACE_IO_Cntl_Msg::SET_HWM:
+ this->water_marks (command, *(size_t *) mb->cont ()->rd_ptr ());
+ break;
+ default:
+ return -1;
+ }
+ return 0;
+}
+
+#if 0
+
+// Right now, Peer_Handlers are purely Reactive, i.e., they all run in
+// a single thread of control. It would be easy to make them Active
+// Objects by calling activate() in Peer_Handler::open(), making
+// Peer_Handler::put() enqueue each message on the message queue, and
+// (3) then running the following svc() routine to route each message
+// to its final destination within a separate thread. Note that we'd
+// want to move the svc() call up to the Consumer_Router and
+// Supplier_Router level in order to get the right level of control
+// for input and output.
+
+Peer_Handler::svc (void)
+{
+ ACE_Message_Block *db, *hb;
+
+ // Do an endless loop
+ for (;;)
+ {
+ db = new Message_Block (BUFSIZ);
+ hb = new Message_Block (sizeof (ROUTING_KEY),
+ Message_Block::MB_PROTO,
+ db);
+
+ ssize_t n = this->peer_.recv (db->rd_ptr (), db->size ());
+
+ if (n == -1)
+ LM_ERROR_RETURN ((LOG_ERROR,
+ ACE_TEXT ("%p"),
+ ACE_TEXT ("recv failed")),
+ -1);
+ else if (n == 0) // Client has closed down the connection.
+ {
+ if (this->peer_router_context_->peer_router ()->unbind_peer (this->get_handle ()) == -1)
+ LM_ERROR_RETURN ((LOG_ERROR,
+ ACE_TEXT ("%p"),
+ ACE_TEXT ("unbind failed")),
+ -1);
+ LM_DEBUG ((LOG_DEBUG,
+ ACE_TEXT ("(%t) shutting down \n")));
+
+ // We do not need to be deregistered by reactor
+ // as we were not registered at all.
+ return -1;
+ }
+ else
+ {
+ // Transform incoming buffer into a Message.
+ db->wr_ptr (n);
+ *(long *) hb->rd_ptr () = this->get_handle (); // Structure assignment.
+ hb->wr_ptr (sizeof (long));
+
+ // Pass the message to the stream.
+ if (this->peer_router_context_->peer_router ()->reply (hb) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("(%t) %p\n"),
+ ACE_TEXT ("Peer_Handler.svc : peer_router->reply failed")),
+ -1);
+ }
+ }
+ return 0;
+}
+#endif /* 0 */
+#endif /* _PEER_ROUTER_C */
+
diff --git a/ACE/examples/ASX/Event_Server/Event_Server/Peer_Router.h b/ACE/examples/ASX/Event_Server/Event_Server/Peer_Router.h
new file mode 100644
index 00000000000..044ef07ea07
--- /dev/null
+++ b/ACE/examples/ASX/Event_Server/Event_Server/Peer_Router.h
@@ -0,0 +1,158 @@
+/* -*- C++ -*- */
+// $Id$
+
+#ifndef _PEER_ROUTER_H
+#define _PEER_ROUTER_H
+
+#include "ace/Acceptor.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/SOCK_Acceptor.h"
+#include "ace/Svc_Handler.h"
+#include "ace/Map_Manager.h"
+#include "ace/RW_Thread_Mutex.h"
+
+// Type of search key for CONSUMER_MAP
+typedef ACE_HANDLE ROUTING_KEY;
+
+// Forward declarations.
+class Peer_Router;
+class Peer_Router_Context;
+
+class Peer_Handler : public ACE_Svc_Handler<ACE_SOCK_STREAM, ACE_SYNCH>
+{
+ // = TITLE
+ // Receive input from a Peer and forward to the appropriate
+ // <Peer_Router> (i.e., <Consumer_Router> or <Supplier_Router>).
+public:
+ Peer_Handler (Peer_Router_Context * = 0);
+ // Initialization method.
+
+ virtual int open (void * = 0);
+ // Called by the ACE_Acceptor::handle_input() to activate this
+ // object.
+
+ virtual int handle_input (ACE_HANDLE);
+ // Receive input from a peer.
+
+ virtual int put (ACE_Message_Block *, ACE_Time_Value *tv = 0);
+ // Send output to a peer. Note that this implementation "blocks" if
+ // flow control occurs. This is undesirable for "real"
+ // applications. The best way around this is to make the
+ // <Peer_Handler> an Active Object, e.g., as done in the
+ // $ACE_ROOT/apps/Gateway/Gateway application.
+
+protected:
+ Peer_Router_Context *peer_router_context_;
+ // Pointer to router context. This maintains the state that is
+ // shared by both Tasks in a <Peer_Router> Module.
+};
+
+class Peer_Router_Context : public ACE_Acceptor<Peer_Handler, ACE_SOCK_ACCEPTOR>
+{
+ // = TITLE
+ // Defines state and behavior shared between both Tasks in a
+ // <Peer_Router> Module.
+ //
+ // = DESCRIPTION
+ // This class also serves as an <ACE_Acceptor>, which creates
+ // <Peer_Handlers> when Peers connect.
+public:
+ // = Initialization and termination methods.
+ Peer_Router_Context (u_short port);
+ // Constructor.
+
+ virtual int unbind_peer (ROUTING_KEY);
+ // Remove the <Peer_Handler *> from the <PEER_MAP> that corresponds
+ // to the <ROUTING_KEY>.
+
+ virtual int bind_peer (ROUTING_KEY, Peer_Handler *);
+ // Add a <Peer_Handler> to the <PEER_MAP> that's associated with the
+ // <ROUTING_KEY>.
+
+ int send_peers (ACE_Message_Block *mb);
+ // Send the <ACE_Message_Block> to all the peers. Note that in a
+ // "real" application this logic would most likely be more
+ // selective, i.e., it would actually do "routing" based on
+ // addressing information passed in the <ACE_Message_Block>.
+
+ int make_svc_handler (Peer_Handler *&sh);
+ // Factory Method that creates a new <Peer_Handler> for each
+ // connection. This method overrides the default behavior in
+ // <ACE_Acceptor>.
+
+ // = Set/Get Router Task.
+ Peer_Router *peer_router (void);
+ void peer_router (Peer_Router *);
+
+ void release (void);
+ // Decrement the reference count and delete <this> when count == 0;
+
+ void duplicate (void);
+ // Increment the reference count.
+
+private:
+ Peer_Router *peer_router_;
+ // Pointer to the <Peer_Router> that we are accepting for.
+
+ // = Useful typedefs.
+ typedef ACE_Map_Manager <ROUTING_KEY, Peer_Handler *, ACE_SYNCH_RW_MUTEX>
+ PEER_MAP;
+ typedef ACE_Map_Iterator<ROUTING_KEY, Peer_Handler *, ACE_SYNCH_RW_MUTEX>
+ PEER_ITERATOR;
+ typedef ACE_Map_Entry<ROUTING_KEY, Peer_Handler *>
+ PEER_ENTRY;
+
+ PEER_MAP peer_map_;
+ // Map used to keep track of active peers.
+
+ int reference_count_;
+ // Keep track of when we can delete ourselves.
+
+ ~Peer_Router_Context (void);
+ // Private to ensure dynamic allocation.
+
+ friend class Friend_Of_Peer_Router_Context;
+ // Declare a friend class to avoid compiler warnings because the
+ // destructor is private.
+};
+
+class Peer_Router : public ACE_Task<ACE_SYNCH>
+{
+ // = TITLE
+ // This abstract base class provides mechanisms for routing
+ // messages to/from a <ACE_Stream> from/to one or more peers (which
+ // are typically running on remote hosts).
+ //
+ // = DESCRIPTION
+ // Subclasses of <Peer_Router> (such as <Consumer_Router> or
+ // <Supplier_Router>) override the <open>, <close>, and
+ // <put> methods to specialize the behavior of the router to
+ // meet application-specific requirements.
+protected:
+ Peer_Router (Peer_Router_Context *prc);
+ // Initialization method.
+
+ virtual int control (ACE_Message_Block *);
+ // Handle control messages arriving from adjacent Modules.
+
+ Peer_Router_Context *context (void) const;
+ // Returns the routing context.
+
+ typedef ACE_Task<ACE_SYNCH> inherited;
+ // Helpful typedef.
+
+private:
+ Peer_Router_Context *peer_router_context_;
+ // Reference to the context shared by the writer and reader Tasks,
+ // e.g., in the <Consumer_Router> and <Supplier_Router> Modules.
+
+ // = Prevent copies and pass-by-value.
+ Peer_Router (const Peer_Router &);
+ void operator= (const Peer_Router &);
+};
+
+#endif /* _PEER_ROUTER_H */
diff --git a/ACE/examples/ASX/Event_Server/Event_Server/Supplier_Router.cpp b/ACE/examples/ASX/Event_Server/Event_Server/Supplier_Router.cpp
new file mode 100644
index 00000000000..72c43ee6312
--- /dev/null
+++ b/ACE/examples/ASX/Event_Server/Event_Server/Supplier_Router.cpp
@@ -0,0 +1,165 @@
+// $Id$
+
+#include "ace/os_include/os_assert.h"
+#include "ace/OS_NS_stdio.h"
+#include "ace/OS_NS_string.h"
+#include "Supplier_Router.h"
+#include "Options.h"
+
+ACE_RCSID(Event_Server, Supplier_Router, "$Id$")
+
+// Handle outgoing messages in a separate thread.
+
+int
+Supplier_Router::svc (void)
+{
+ assert (this->is_writer ());
+
+ ACE_DEBUG ((LM_DEBUG, "(%t) starting svc in Supplier_Router\n"));
+
+ for (ACE_Message_Block *mb = 0;
+ this->getq (mb) >= 0;
+ )
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ "(%t) warning: Supplier_Router is "
+ "forwarding a message via send_peers\n"));
+
+ // Broadcast the message to the Suppliers, even though this is
+ // "incorrect" (assuming a oneway flow of events from Suppliers
+ // to Consumers)!
+
+ if (this->context ()->send_peers (mb) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "(%t) send_peers failed in Supplier_Router\n"),
+ -1);
+ }
+
+ ACE_DEBUG ((LM_DEBUG,
+ "(%t) stopping svc in Supplier_Router\n"));
+ return 0;
+}
+
+Supplier_Router::Supplier_Router (Peer_Router_Context *prc)
+ : Peer_Router (prc)
+{
+ // Increment the reference count.
+ this->context ()->duplicate ();
+}
+
+// Initialize the Supplier Router.
+
+int
+Supplier_Router::open (void *)
+{
+ if (this->is_reader ())
+ {
+ // Set the <Peer_Router_Context> to point back to us so that all
+ // the Peer_Handler's <put> their incoming <Message_Blocks> to
+ // our reader Task.
+ this->context ()->peer_router (this);
+ return 0;
+ }
+
+ else // if (this->is_writer ()
+ {
+ // Increment the reference count.
+ this->context ()->duplicate ();
+
+ // Make this an active object to handle the error cases in a
+ // separate thread.
+ return this->activate (Options::instance ()->t_flags ());
+ }
+}
+
+// Close down the router.
+
+int
+Supplier_Router::close (u_long)
+{
+ ACE_DEBUG ((LM_DEBUG,
+ "(%t) closing Supplier_Router %s\n",
+ this->is_reader () ? "reader" : "writer"));
+
+ if (this->is_writer ())
+ // Inform the thread to shut down.
+ this->msg_queue ()->deactivate ();
+
+ // Both writer and reader call release(), so the context knows when
+ // to clean itself up.
+ this->context ()->release ();
+ return 0;
+}
+
+// Send an <ACE_Message_Block> to the supplier(s).
+
+int
+Supplier_Router::put (ACE_Message_Block *mb,
+ ACE_Time_Value *)
+{
+ // Perform the necessary control operations before passing
+ // the message up the stream.
+
+ if (mb->msg_type () == ACE_Message_Block::MB_IOCTL)
+ {
+ this->control (mb);
+ return this->put_next (mb);
+ }
+
+ // If we're the reader then we are responsible for pass messages up
+ // to the next Module's reader Task. Note that in a "real"
+ // application this is likely where we'd take a look a the actual
+ // information that was in the message, e.g., in order to figure out
+ // what operation it was and what it's "parameters" where, etc.
+ else if (this->is_reader ())
+ return this->put_next (mb);
+
+ else // if (this->is_writer ())
+ {
+ // Someone is trying to write to the Supplier. In this
+ // implementation this is considered an "error." However, we'll
+ // just go ahead and forward the message to the Supplier (who
+ // hopefully is prepared to receive it).
+ ACE_DEBUG ((LM_WARNING,
+ "(%t) warning: sending to a Supplier\n"));
+
+ // Queue up the message to processed by <Supplier_Router::svc>.
+ // Since we don't expect to be getting many of these messages,
+ // we queue them up and run them in a separate thread to avoid
+ // taxing the main thread.
+ return this->putq (mb);
+ }
+}
+
+// Return information about the <Supplier_Router>.
+#if defined (ACE_WIN32) || !defined (ACE_USES_WCHAR)
+# define FMTSTR ACE_TEXT ("%s\t %d/%s %s (%s)\n")
+#else
+# define FMTSTR ACE_TEXT ("%ls\t %d/%ls %ls (%ls)\n")
+#endif /* ACE_WIN32 || !ACE_USES_WCHAR */
+
+int
+Supplier_Router::info (ACE_TCHAR **strp, size_t length) const
+{
+ ACE_TCHAR buf[BUFSIZ];
+ ACE_INET_Addr addr;
+ const ACE_TCHAR *mod_name = this->name ();
+
+ if (this->context ()->acceptor ().get_local_addr (addr) == -1)
+ return -1;
+
+ ACE_OS::sprintf (buf,
+ FMTSTR,
+ mod_name,
+ addr.get_port_number (),
+ ACE_TEXT ("tcp"),
+ ACE_TEXT ("# supplier router"),
+ this->is_reader () ?
+ ACE_TEXT ("reader") : ACE_TEXT ("writer"));
+ if (*strp == 0 && (*strp = ACE_OS::strdup (mod_name)) == 0)
+ return -1;
+ else
+ ACE_OS::strncpy (*strp, mod_name, length);
+
+ return ACE_OS::strlen (mod_name);
+}
diff --git a/ACE/examples/ASX/Event_Server/Event_Server/Supplier_Router.h b/ACE/examples/ASX/Event_Server/Event_Server/Supplier_Router.h
new file mode 100644
index 00000000000..8a42943c147
--- /dev/null
+++ b/ACE/examples/ASX/Event_Server/Event_Server/Supplier_Router.h
@@ -0,0 +1,72 @@
+/* -*- C++ -*- */
+// $Id$
+
+#ifndef _SUPPLIER_ROUTER_H
+#define _SUPPLIER_ROUTER_H
+
+#include "ace/INET_Addr.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/SOCK_Acceptor.h"
+#include "ace/Map_Manager.h"
+#include "ace/Svc_Handler.h"
+#include "Peer_Router.h"
+
+class Supplier_Router : public Peer_Router
+{
+ // = TITLE
+ // Provides the interface between one or more Suppliers and the
+ // Event Server ACE_Stream.
+ //
+ // = DESCRIPTION
+ // This class normally sits on "bottom" of the Stream and sends
+ // all messages coming from Suppliers via its "write" <Task>
+ // "upstream" to all the Consumers connected to the
+ // <Consumer_Router>. Normally, the messages flow up the
+ // stream to <Consumer_Router>s. However, if Consumers
+ // transmit data to the <Consumer_Router>, we dutifully push it
+ // out to the Suppliers via the <Supplier_Router>.
+ //
+ // When used on the "reader" side of a Stream, the
+ // <Supplier_Router> simply forwards all messages up the stream.
+ // When used on the "writer" side, the <Supplier_Router> queues
+ // up outgoing messages to suppliers and sends them in a
+ // separate thread. The reason for this is that it's really an
+ // "error" for a <Supplier_Router> to send messages to
+ // Suppliers, so we don't expect this to happen very much. When
+ // it does we use a separate thread to avoid taxing the main
+ // thread, which processes "normal" messages.
+ //
+ // All of these methods are called via base class pointers by
+ // the <ACE_Stream> apparatus. Therefore, we can put them in
+ // the protected section.
+public:
+ Supplier_Router (Peer_Router_Context *prc);
+ // Initialization method.
+
+protected:
+ // = ACE_Task hooks.
+
+ virtual int open (void *a = 0);
+ // Called by the Stream to initialize the router.
+
+ virtual int close (u_long flags = 0);
+ // Called by the Stream to shutdown the router.
+
+ virtual int put (ACE_Message_Block *msg, ACE_Time_Value * = 0);
+ // Called by the <SUPPLIER_HANDLER> to pass a message to the Router.
+ // The Router queues up this message, which is then processed in the
+ // <svc> method in a separate thread.
+
+ virtual int svc (void);
+ // Runs in a separate thread to dequeue messages and pass them up
+ // the stream.
+
+ virtual int info (ACE_TCHAR **info_string, size_t length) const;
+ // Dynamic linking hook.
+};
+
+#endif /* _SUPPLIER_ROUTER_H */
diff --git a/ACE/examples/ASX/Event_Server/Event_Server/event_server.cpp b/ACE/examples/ASX/Event_Server/Event_Server/event_server.cpp
new file mode 100644
index 00000000000..3858bad1fc2
--- /dev/null
+++ b/ACE/examples/ASX/Event_Server/Event_Server/event_server.cpp
@@ -0,0 +1,258 @@
+// $Id$
+
+// Main driver program for the event server example.
+
+#include "ace/OS_main.h"
+#include "ace/Service_Config.h"
+#include "ace/OS_NS_unistd.h"
+#include "Options.h"
+#include "Consumer_Router.h"
+#include "Event_Analyzer.h"
+#include "Supplier_Router.h"
+#include "ace/Sig_Adapter.h"
+#include "ace/Stream.h"
+
+ACE_RCSID (Event_Server,
+ event_server,
+ "$Id$")
+
+// Typedef these components to handle multi-threading correctly.
+typedef ACE_Stream<ACE_SYNCH> MT_Stream;
+typedef ACE_Module<ACE_SYNCH> MT_Module;
+
+
+class Event_Server : public ACE_Sig_Adapter
+{
+ // = TITLE
+ // Run the logic for the <Event_Server>.
+
+ //
+ // = DESCRIPTION
+ // In addition to packaging the <Event_Server> components, this
+ // class also handles SIGINT and terminate the entire
+ // application process. There are several ways to terminate
+ // this application process:
+ //
+ // 1. Send a SIGINT signal (e.g., via ^C)
+ // 2. Type any character on the STDIN.
+ //
+ // Note that by inheriting from the <ACE_Sig_Adapter> we can
+ // shutdown the <ACE_Reactor> cleanly when a SIGINT is
+ // generated.
+public:
+ Event_Server (void);
+ // Constructor.
+
+ int svc (void);
+ // Run the event-loop for the event server.
+
+private:
+ virtual int handle_input (ACE_HANDLE handle);
+ // Hook method called back when a user types something into the
+ // STDIN in order to shut down the program.
+
+ int configure_stream (void);
+ // Setup the plumbing in the stream.
+
+ int set_watermarks (void);
+ // Set the high and low queue watermarks.
+
+ int run_event_loop (void);
+ // Run the event-loop for the <Event_Server>.
+
+ MT_Stream event_server_;
+ // The <ACE_Stream> that contains the <Event_Server> application
+ // <Modules>.
+};
+
+Event_Server::Event_Server (void)
+ : ACE_Sig_Adapter (ACE_Sig_Handler_Ex (ACE_Reactor::end_event_loop))
+ // Shutdown the <ACE_Reactor>'s event loop when a SIGINT is
+ // received.
+{
+ // Register to trap STDIN from the user.
+ if (ACE_Event_Handler::register_stdin_handler (this,
+ ACE_Reactor::instance (),
+ ACE_Thread_Manager::instance ()) == -1)
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("register_stdin_handler")));
+ // Register to trap the SIGINT signal.
+ else if (ACE_Reactor::instance ()->register_handler
+ (SIGINT, this) == -1)
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("register_handler")));
+}
+
+int
+Event_Server::handle_input (ACE_HANDLE)
+{
+ // This code here will make sure we actually wait for the user to
+ // type something. On platforms like Win32, <handle_input> is called
+ // prematurely (even when there is no data).
+ char temp_buffer [BUFSIZ];
+
+ ssize_t n = ACE_OS::read (ACE_STDIN,
+ temp_buffer,
+ sizeof (temp_buffer));
+ // This ought to be > 0, otherwise something very strange has
+ // happened!!
+ ACE_ASSERT (n > 0);
+ ACE_UNUSED_ARG (n); // To avoid compile warning with ACE_NDEBUG.
+
+ Options::instance ()->stop_timer ();
+
+ ACE_DEBUG ((LM_INFO,
+ ACE_TEXT ("(%t) closing down the test\n")));
+ Options::instance ()->print_results ();
+
+ ACE_Reactor::instance ()->end_reactor_event_loop ();
+ return -1;
+}
+
+int
+Event_Server::configure_stream (void)
+{
+ Peer_Router_Context *src;
+ // Create the <Supplier_Router>'s routing context. This contains a
+ // context shared by both the write-side and read-side of the
+ // <Supplier_Router> Module.
+ ACE_NEW_RETURN (src,
+ Peer_Router_Context (Options::instance ()->supplier_port ()),
+ -1);
+
+ MT_Module *srm = 0;
+ // Create the <Supplier_Router> module.
+ ACE_NEW_RETURN (srm,
+ MT_Module
+ (ACE_TEXT ("Supplier_Router"),
+ new Supplier_Router (src),
+ new Supplier_Router (src)),
+ -1);
+
+ MT_Module *eam = 0;
+ // Create the <Event_Analyzer> module.
+ ACE_NEW_RETURN (eam,
+ MT_Module
+ (ACE_TEXT ("Event_Analyzer"),
+ new Event_Analyzer,
+ new Event_Analyzer),
+ -1);
+
+ Peer_Router_Context *crc;
+ // Create the <Consumer_Router>'s routing context. This contains a
+ // context shared by both the write-side and read-side of the
+ // <Consumer_Router> Module.
+ ACE_NEW_RETURN (crc,
+ Peer_Router_Context (Options::instance ()->consumer_port ()),
+ -1);
+
+ MT_Module *crm = 0;
+ // Create the <Consumer_Router> module.
+ ACE_NEW_RETURN (crm,
+ MT_Module
+ (ACE_TEXT ("Consumer_Router"),
+ new Consumer_Router (crc),
+ new Consumer_Router (crc)),
+ -1);
+
+ // Push the Modules onto the event_server stream.
+
+ if (this->event_server_.push (srm) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("push (Supplier_Router)")),
+ -1);
+ else if (this->event_server_.push (eam) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("push (Event_Analyzer)")),
+ -1);
+ else if (this->event_server_.push (crm) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("push (Consumer_Router)")),
+ -1);
+ return 0;
+}
+
+int
+Event_Server::set_watermarks (void)
+{
+ // Set the high and low water marks appropriately. The water marks
+ // control how much data can be buffered before the queues are
+ // considered "full."
+ size_t wm = Options::instance ()->low_water_mark ();
+
+ if (this->event_server_.control (ACE_IO_Cntl_Msg::SET_LWM,
+ &wm) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("%p\n"),
+ ACE_TEXT ("push (setting low watermark)")),
+ -1);
+
+ wm = Options::instance ()->high_water_mark ();
+ if (this->event_server_.control (ACE_IO_Cntl_Msg::SET_HWM,
+ &wm) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("%p\n"),
+ ACE_TEXT ("push (setting high watermark)")),
+ -1);
+ return 0;
+}
+
+int
+Event_Server::run_event_loop (void)
+{
+ // Begin the timer.
+ Options::instance ()->start_timer ();
+
+ // Perform the main event loop waiting for the user to type ^C or to
+ // enter a line on the ACE_STDIN.
+
+ ACE_Reactor::instance ()->run_reactor_event_loop ();
+
+ // Close down the stream and call the <close> hooks on all the
+ // <ACE_Task>s in the various Modules in the Stream.
+ this->event_server_.close ();
+
+ // Wait for the threads in the <Consumer_Router> and
+ // <Supplier_Router> to exit.
+ return ACE_Thread_Manager::instance ()->wait ();
+}
+
+int
+Event_Server::svc (void)
+{
+ if (this->configure_stream () == -1)
+ return -1;
+ else if (this->set_watermarks () == -1)
+ return -1;
+ else if (this->run_event_loop () == -1)
+ return -1;
+ else
+ return 0;
+}
+
+int
+ACE_TMAIN (int argc, ACE_TCHAR *argv[])
+{
+#if defined (ACE_HAS_THREADS)
+ Options::instance ()->parse_args (argc, argv);
+
+ // Initialize the <Event_Server>.
+ Event_Server event_server;
+
+ // Run the event server's event-loop.
+ int result = event_server.svc ();
+
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("exiting main\n")));
+
+ return result;
+#else
+ ACE_UNUSED_ARG (argc);
+ ACE_UNUSED_ARG (argv);
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("threads not supported on this platform\n")),
+ 1);
+#endif /* ACE_HAS_THREADS */
+}
diff --git a/ACE/examples/ASX/Event_Server/Makefile.am b/ACE/examples/ASX/Event_Server/Makefile.am
new file mode 100644
index 00000000000..b337a11860a
--- /dev/null
+++ b/ACE/examples/ASX/Event_Server/Makefile.am
@@ -0,0 +1,14 @@
+## Process this file with automake to create Makefile.in
+##
+## $Id$
+##
+## This file was generated by MPC. Any changes made directly to
+## this file will be lost the next time it is generated.
+##
+## MPC Command:
+## /acebuilds/ACE_wrappers-repository/bin/mwc.pl -include /acebuilds/MPC/config -include /acebuilds/MPC/templates -feature_file /acebuilds/ACE_wrappers-repository/local.features -noreldefs -type automake -exclude build,Kokyu
+
+SUBDIRS = \
+ Event_Server \
+ Transceiver
+
diff --git a/ACE/examples/ASX/Event_Server/README b/ACE/examples/ASX/Event_Server/README
new file mode 100644
index 00000000000..262b7ee9633
--- /dev/null
+++ b/ACE/examples/ASX/Event_Server/README
@@ -0,0 +1,79 @@
+This subdirectory illustrates a number of the ACE ASX framework
+features using an ACE_Stream application called the Event Server. For
+more information on the design and use of the ACE ASX framework please
+see http://www.cs.wustl.edu/~schmidt/C++-USENIX-94.ps.gz and
+http://www.cs.wustl.edu/~schmidt/ACE-concurrency.ps.gz. For more
+information on the Event Server, please see
+http://www.cs.wustl.edu/~schmidt/DSEJ-94.ps.gz.
+
+The Event Server example works as follows:
+
+1. When the ./Event_Server/event_server executable is run it
+ creates two SOCK_Acceptors, which listen for and accept incoming
+ connections from Consumers and Suppliers.
+
+2. The ./Event_Server/Transceiver/transceiver application plays
+ the role of either a Consumer or a Supplier (with the current
+ implementation it can only play one role at a time). The
+ transceiver process can be started multiple times. Each call
+ should be either:
+
+ # Consumer
+ % transceiver -p 10002 -h hostname -C
+
+ or
+
+ # Supplier
+ % transceiver -p 10003 -h hostname -S
+
+ where 10002 and 10003 are the default Consumer listening port and
+ the Supplier listening port, respectively, on the event server,
+ "hostname" is the name of the machine the event_server is running,
+ and -C and -S indicate that the transceiver plays the role of a
+ Consumer or Supplier, respectively. I typically run the
+ Consumer(s) and Supplier(s) in different windows to make it easier
+ to understand the output.
+
+3. Once the Consumer(s) and Supplier(s) are connected, you can
+ type data from any Supplier window. This data will be routed
+ through the Modules/Tasks in the event_server's Stream and be
+ forwarded to the Consumer(s).
+
+ Since the transceivers are full-duplex you can also send messages
+ from the Consumer(s) to Supplier(s). However, the Event Server will
+ warn you about this since it's not really kosher to have Consumers
+ sending to Suppliers...
+
+4. When you want to shut down the tranceivers or event server
+ just type ^C (which generates a SIGINT) or type any input in the
+ window running the Event Server application.
+
+What makes this example particularly interesting is that once you've
+got the hang of the ASX Streams architecture, you can "push" new
+filtering Modules onto the event_server Stream and modify the
+application's behavior transparently to the other components.
+
+There are a bunch of features that aren't implemented in this
+prototype that you'd probably want to do for a "real" application.
+Some of the more interesting things to add would be:
+
+0. Complete "full-duplex" support, i.e., Peers could play the
+ role of Suppliers and Consumers simultaneously.
+
+1. Support for "commands", which would change the behavior
+ of the Event_Server based on messages it got from Suppliers
+ (or Consumers).
+
+3. Support for "pull" operations, as well as "push" operations.
+ This would basically involve adding a "MIB Module" to get/set
+ the "values" associated with "names" passed in by Peers. This
+ could probably replace the Event_Analysis Module.
+
+4. Filtering and correlation (this should probably be done
+ via a separate Module that handles filtering and correlation).
+
+5. More flexible concurrency model(s), e.g., "Active Object per-Consumer".
+ This would enable the Event Server process to handle flow control
+ more gracefully than it does not (it currently "hangs," which isn't
+ desirable).
+
diff --git a/ACE/examples/ASX/Event_Server/Transceiver/Makefile.am b/ACE/examples/ASX/Event_Server/Transceiver/Makefile.am
new file mode 100644
index 00000000000..9407ab5873b
--- /dev/null
+++ b/ACE/examples/ASX/Event_Server/Transceiver/Makefile.am
@@ -0,0 +1,34 @@
+## Process this file with automake to create Makefile.in
+##
+## $Id$
+##
+## This file was generated by MPC. Any changes made directly to
+## this file will be lost the next time it is generated.
+##
+## MPC Command:
+## /acebuilds/ACE_wrappers-repository/bin/mwc.pl -include /acebuilds/MPC/config -include /acebuilds/MPC/templates -feature_file /acebuilds/ACE_wrappers-repository/local.features -noreldefs -type automake -exclude build,Kokyu
+
+ACE_BUILDDIR = $(top_builddir)
+ACE_ROOT = $(top_srcdir)
+
+## Makefile.Transceiver.am
+noinst_PROGRAMS = Transceiver
+
+Transceiver_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+Transceiver_SOURCES = \
+ transceiver.cpp \
+ transceiver.h
+
+Transceiver_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Clean up template repositories, etc.
+clean-local:
+ -rm -f *~ *.bak *.rpo *.sym lib*.*_pure_* core core.*
+ -rm -f gcctemp.c gcctemp so_locations *.ics
+ -rm -rf cxx_repository ptrepository ti_files
+ -rm -rf templateregistry ir.out
+ -rm -rf ptrepository SunWS_cache Templates.DB
diff --git a/ACE/examples/ASX/Event_Server/Transceiver/Transceiver.mpc b/ACE/examples/ASX/Event_Server/Transceiver/Transceiver.mpc
new file mode 100644
index 00000000000..a6a3309727c
--- /dev/null
+++ b/ACE/examples/ASX/Event_Server/Transceiver/Transceiver.mpc
@@ -0,0 +1,9 @@
+// -*- MPC -*-
+// $Id$
+
+project(*) : aceexe {
+ exename = Transceiver
+ Source_Files {
+ transceiver.cpp
+ }
+}
diff --git a/ACE/examples/ASX/Event_Server/Transceiver/transceiver.cpp b/ACE/examples/ASX/Event_Server/Transceiver/transceiver.cpp
new file mode 100644
index 00000000000..37bbaad7d3d
--- /dev/null
+++ b/ACE/examples/ASX/Event_Server/Transceiver/transceiver.cpp
@@ -0,0 +1,238 @@
+// $Id$
+
+// Test program for the event transceiver. This program can play the
+// role of either Consumer or Supplier. You can terminate this
+// program by typing ^C....
+
+#include "ace/OS_main.h"
+#include "ace/OS_NS_string.h"
+#include "ace/Service_Config.h"
+#include "ace/SOCK_Connector.h"
+#include "ace/Connector.h"
+#include "ace/Get_Opt.h"
+#include "ace/Signal.h"
+#include "ace/OS_NS_unistd.h"
+
+#include "transceiver.h"
+
+ACE_RCSID (Transceiver,
+ transceiver,
+ "$Id$")
+
+// Handle the command-line arguments.
+
+int
+Event_Transceiver::parse_args (int argc, ACE_TCHAR *argv[])
+{
+ ACE_Get_Opt get_opt (argc, argv, ACE_TEXT ("Ch:p:S"));
+
+ this->port_number_ = ACE_DEFAULT_SERVER_PORT;
+ this->host_name_ = ACE_DEFAULT_SERVER_HOST;
+ this->role_ = ACE_TEXT ("Supplier");
+
+ for (int c; (c = get_opt ()) != -1; )
+ switch (c)
+ {
+ case 'C':
+ this->role_ = ACE_TEXT ("Consumer");
+ break;
+ case 'h':
+ this->host_name_ = get_opt.opt_arg ();
+ break;
+ case 'p':
+ this->port_number_ = ACE_OS::atoi (get_opt.opt_arg ());
+ break;
+ case 'S':
+ this->role_ = ACE_TEXT ("Supplier");
+ break;
+ default:
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("usage: %n [-CS] [-h host_name] [-p portnum] \n")),
+ -1);
+ /* NOTREACHED */
+ break;
+ }
+
+ // Increment by 1 if we're the supplier to mirror the default
+ // behavior of the Event_Server (which sets the Consumer port to
+ // ACE_DEFAULT_SERVER_PORT and the Supplier port to
+ // ACE_DEFAULT_SERVER_PORT + 1). Note that this is kind of a
+ // hack...
+ if (ACE_OS::strcmp (this->role_, ACE_TEXT ("Supplier")) == 0
+ && this->port_number_ == ACE_DEFAULT_SERVER_PORT)
+ this->port_number_++;
+ return 0;
+}
+
+int
+Event_Transceiver::handle_close (ACE_HANDLE,
+ ACE_Reactor_Mask)
+{
+ ACE_Reactor::instance ()->end_reactor_event_loop ();
+ return 0;
+}
+
+// Close down via SIGINT or SIGQUIT.
+
+int
+Event_Transceiver::handle_signal (int,
+ siginfo_t *,
+ ucontext_t *)
+{
+ ACE_Reactor::instance ()->end_reactor_event_loop ();
+ return 0;
+}
+
+Event_Transceiver::Event_Transceiver (void)
+{
+}
+
+Event_Transceiver::Event_Transceiver (int argc, ACE_TCHAR *argv[])
+{
+ if (this->parse_args (argc, argv) == -1)
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("parse_args")));
+ else
+ {
+ ACE_Sig_Set sig_set;
+
+ sig_set.sig_add (SIGINT);
+ sig_set.sig_add (SIGQUIT);
+
+ // Register to handle the SIGINT and SIGQUIT signals.
+ if (ACE_Reactor::instance ()->register_handler
+ (sig_set,
+ this) == -1)
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("register_handler")));
+
+ // We need to register <this> here before we're connected since
+ // otherwise <get_handle> will return the connection socket
+ // handle for the peer.
+ else if (ACE_Event_Handler::register_stdin_handler (this,
+ ACE_Reactor::instance (),
+ ACE_Thread_Manager::instance ()) == -1)
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("register_stdin_handler")));
+
+ // Address of the server.
+ ACE_INET_Addr server_addr (this->port_number_,
+ this->host_name_);
+
+ ACE_Connector<Event_Transceiver, ACE_SOCK_CONNECTOR> connector;
+
+ // We need a pointer here because connect takes a reference to a
+ // pointer!
+ Event_Transceiver *etp = this;
+
+ // Establish the connection to the Event Server.
+ if (connector.connect (etp,
+ server_addr) == -1)
+ {
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ this->host_name_));
+ ACE_Reactor::instance()->remove_handler (sig_set);
+ ACE_Event_Handler::remove_stdin_handler (ACE_Reactor::instance(),
+ ACE_Thread_Manager::instance());
+ }
+ }
+}
+
+int
+Event_Transceiver::open (void *)
+{
+ // Register ourselves to be notified when there's data to read on
+ // the socket.
+ if (ACE_Reactor::instance ()->register_handler
+ (this,
+ ACE_Event_Handler::READ_MASK) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("register_handler")),
+ -1);
+ return 0;
+}
+
+int
+Event_Transceiver::handle_input (ACE_HANDLE handle)
+{
+ // Determine whether we play the role of a consumer or a supplier.
+ if (handle == ACE_STDIN)
+ return this->transmitter ();
+ else
+ return this->receiver ();
+}
+
+int
+Event_Transceiver::transmitter (void)
+{
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("(%P|%t) entering %s transmitter\n"),
+ this->role_));
+
+ char buf[BUFSIZ];
+ ssize_t n = ACE_OS::read (ACE_STDIN, buf, sizeof buf);
+ int result = 0;
+
+ if (n <= 0 || this->peer ().send_n (buf, n) != n)
+ result = -1;
+
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("(%P|%t) leaving %s transmitter\n"),
+ this->role_));
+ return result;
+}
+
+int
+Event_Transceiver::receiver (void)
+{
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("(%P|%t) entering %s receiver\n"),
+ this->role_));
+
+ char buf[BUFSIZ];
+
+ ssize_t n = this->peer ().recv (buf, sizeof buf);
+ int result = 0;
+
+ if (n <= 0
+ || ACE_OS::write (ACE_STDOUT, buf, n) != n)
+ result = -1;
+
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("(%P|%t) leaving %s receiver\n"),
+ this->role_));
+ return result;
+}
+
+int
+ACE_TMAIN (int argc, ACE_TCHAR *argv[])
+{
+ if (ACE_Service_Config::open (argv[0]) == -1
+ && errno != ENOENT)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("open")),
+ -1);
+
+ // Create and initialize the transceiver.
+ Event_Transceiver transceiver (argc, argv);
+
+ // Demonstrate how we can check if a constructor failed...
+ if (ACE_LOG_MSG->op_status () == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("Event_Transceiver constructor failed")),
+ -1);
+
+
+ // Run event loop until either the event server shuts down or we get
+ // a SIGINT.
+ ACE_Reactor::instance ()->run_reactor_event_loop ();
+ return 0;
+}
+
diff --git a/ACE/examples/ASX/Event_Server/Transceiver/transceiver.h b/ACE/examples/ASX/Event_Server/Transceiver/transceiver.h
new file mode 100644
index 00000000000..864b88a0b48
--- /dev/null
+++ b/ACE/examples/ASX/Event_Server/Transceiver/transceiver.h
@@ -0,0 +1,60 @@
+/* -*- C++ -*- */
+// $Id$
+
+#ifndef ACE_TRANSCEIVER_H
+#define ACE_TRANSCEIVER_H
+
+#include "ace/SOCK_Stream.h"
+#include "ace/Svc_Handler.h"
+
+class Event_Transceiver : public ACE_Svc_Handler<ACE_SOCK_STREAM, ACE_NULL_SYNCH>
+{
+ // = TITLE
+ // Generate and receives messages from the event server.
+ //
+ // = DESCRIPTION
+ // This class is both a consumer and supplier of events, i.e.,
+ // it's a ``transceiver.''
+public:
+ // = Initialization method.
+ Event_Transceiver (int argc, ACE_TCHAR *argv[]);
+ // Performs the actual initialization.
+
+ Event_Transceiver (void);
+ // No-op constructor (required by the <ACE_Connector>).
+
+ // = Svc_Handler hook called by the <ACE_Connector>.
+ virtual int open (void *);
+ // Initialize the transceiver when we are connected.
+
+ // = Demultplexing hooks from the <ACE_Reactor>.
+ virtual int handle_input (ACE_HANDLE);
+ // Receive data from STDIN or socket.
+
+ virtual int handle_signal (int signum, siginfo_t *, ucontext_t *);
+ // Close down via SIGINT.
+
+ virtual int handle_close (ACE_HANDLE, ACE_Reactor_Mask);
+ // Close down the event loop.
+
+private:
+ int receiver (void);
+ // Reads data from socket and writes to ACE_STDOUT.
+
+ int transmitter (void);
+ // Writes data from ACE_STDIN to socket.
+
+ int parse_args (int argc, ACE_TCHAR *argv[]);
+ // Parse the command-line arguments.
+
+ u_short port_number_;
+ // Port number of event server.
+
+ const ACE_TCHAR *host_name_;
+ // Name of event server.
+
+ const ACE_TCHAR *role_;
+ // Are we playing the Consumer or Supplier role?
+};
+
+#endif /* ACE_TRANSCEIVER_H */
diff --git a/ACE/examples/ASX/Makefile.am b/ACE/examples/ASX/Makefile.am
new file mode 100644
index 00000000000..ecfcb575851
--- /dev/null
+++ b/ACE/examples/ASX/Makefile.am
@@ -0,0 +1,16 @@
+## Process this file with automake to create Makefile.in
+##
+## $Id$
+##
+## This file was generated by MPC. Any changes made directly to
+## this file will be lost the next time it is generated.
+##
+## MPC Command:
+## /acebuilds/ACE_wrappers-repository/bin/mwc.pl -include /acebuilds/MPC/config -include /acebuilds/MPC/templates -feature_file /acebuilds/ACE_wrappers-repository/local.features -noreldefs -type automake -exclude build,Kokyu
+
+SUBDIRS = \
+ CCM_App \
+ Event_Server \
+ Message_Queue \
+ UPIPE_Event_Server
+
diff --git a/ACE/examples/ASX/Message_Queue/.cvsignore b/ACE/examples/ASX/Message_Queue/.cvsignore
new file mode 100644
index 00000000000..2b68761db9c
--- /dev/null
+++ b/ACE/examples/ASX/Message_Queue/.cvsignore
@@ -0,0 +1,6 @@
+bounded_buffer
+bounded_buffer
+buffer_stream
+buffer_stream
+priority_buffer
+priority_buffer
diff --git a/ACE/examples/ASX/Message_Queue/ASX_Message_Queue.mpc b/ACE/examples/ASX/Message_Queue/ASX_Message_Queue.mpc
new file mode 100644
index 00000000000..8c1853bcee7
--- /dev/null
+++ b/ACE/examples/ASX/Message_Queue/ASX_Message_Queue.mpc
@@ -0,0 +1,25 @@
+// -*- MPC -*-
+// $Id$
+
+project(*Bounded_Buffer) : aceexe {
+ exename = bounded_buffer
+ Source_Files {
+ bounded_buffer.cpp
+ }
+}
+
+project(*Buffer_Stream) : aceexe {
+ avoids += uses_wchar
+ exename = buffer_stream
+ Source_Files {
+ buffer_stream.cpp
+ }
+}
+
+project(*Priority_Buffer) : aceexe {
+ exename = priority_buffer
+ Source_Files {
+ priority_buffer.cpp
+ }
+}
+
diff --git a/ACE/examples/ASX/Message_Queue/Makefile.am b/ACE/examples/ASX/Message_Queue/Makefile.am
new file mode 100644
index 00000000000..67e75b6c241
--- /dev/null
+++ b/ACE/examples/ASX/Message_Queue/Makefile.am
@@ -0,0 +1,64 @@
+## Process this file with automake to create Makefile.in
+##
+## $Id$
+##
+## This file was generated by MPC. Any changes made directly to
+## this file will be lost the next time it is generated.
+##
+## MPC Command:
+## /acebuilds/ACE_wrappers-repository/bin/mwc.pl -include /acebuilds/MPC/config -include /acebuilds/MPC/templates -feature_file /acebuilds/ACE_wrappers-repository/local.features -noreldefs -type automake -exclude build,Kokyu
+
+ACE_BUILDDIR = $(top_builddir)
+ACE_ROOT = $(top_srcdir)
+
+
+## Makefile.ASX_Message_Queue_Bounded_Buffer.am
+noinst_PROGRAMS = bounded_buffer
+
+bounded_buffer_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+bounded_buffer_SOURCES = \
+ bounded_buffer.cpp
+
+bounded_buffer_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Makefile.ASX_Message_Queue_Buffer_Stream.am
+
+if !BUILD_USES_WCHAR
+noinst_PROGRAMS += buffer_stream
+
+buffer_stream_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+buffer_stream_SOURCES = \
+ buffer_stream.cpp
+
+buffer_stream_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+endif !BUILD_USES_WCHAR
+
+## Makefile.ASX_Message_Queue_Priority_Buffer.am
+noinst_PROGRAMS += priority_buffer
+
+priority_buffer_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+priority_buffer_SOURCES = \
+ priority_buffer.cpp
+
+priority_buffer_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Clean up template repositories, etc.
+clean-local:
+ -rm -f *~ *.bak *.rpo *.sym lib*.*_pure_* core core.*
+ -rm -f gcctemp.c gcctemp so_locations *.ics
+ -rm -rf cxx_repository ptrepository ti_files
+ -rm -rf templateregistry ir.out
+ -rm -rf ptrepository SunWS_cache Templates.DB
diff --git a/ACE/examples/ASX/Message_Queue/bounded_buffer.cpp b/ACE/examples/ASX/Message_Queue/bounded_buffer.cpp
new file mode 100644
index 00000000000..2cdc50f2116
--- /dev/null
+++ b/ACE/examples/ASX/Message_Queue/bounded_buffer.cpp
@@ -0,0 +1,140 @@
+// $Id$
+
+// This short program copies stdin to stdout via the use of an ASX
+// Message_Queue. It illustrates an implementation of the classic
+// "bounded buffer" program.
+
+#include "ace/Message_Queue.h"
+#include "ace/Thread_Manager.h"
+#include "ace/OS_NS_time.h"
+#include "ace/OS_NS_unistd.h"
+
+ACE_RCSID(Message_Queue, bounded_buffer, "$Id$")
+
+#if defined (ACE_HAS_THREADS)
+
+// The producer reads data from the stdin stream, creates a message,
+// and then queues the message in the message list, where it is
+// removed by the consumer thread. A 0-sized message is enqueued when
+// there is no more data to read. The consumer uses this as a flag to
+// know when to exit.
+
+static void *
+producer (ACE_Message_Queue<ACE_MT_SYNCH> *msg_queue)
+{
+ // Keep reading stdin, until we reach EOF.
+
+ for (int n; ; )
+ {
+ // Allocate a new message.
+ ACE_Message_Block *mb;
+
+ ACE_NEW_RETURN (mb, ACE_Message_Block (BUFSIZ), 0);
+
+ n = ACE_OS::read (ACE_STDIN, mb->wr_ptr (), mb->size ());
+
+ if (n <= 0)
+ {
+ // Send a shutdown message to the other thread and exit.
+ mb->length (0);
+ if (msg_queue->enqueue_tail (mb) == -1)
+ ACE_ERROR ((LM_ERROR,
+ "(%t) %p\n",
+ "put_next"));
+ break;
+ }
+
+ // Send the message to the other thread.
+ else
+ {
+ mb->msg_priority (n);
+ mb->wr_ptr (n);
+ if (msg_queue->enqueue_tail (mb) == -1)
+ ACE_ERROR ((LM_ERROR,
+ "(%t) %p\n",
+ "put_next"));
+ }
+ }
+
+ return 0;
+}
+
+// The consumer dequeues a message from the ACE_Message_Queue, writes
+// the message to the stderr stream, and deletes the message. The
+// producer sends a 0-sized message to inform the consumer to stop
+// reading and exit.
+
+static void *consumer (ACE_Message_Queue<ACE_MT_SYNCH> *msg_queue)
+{
+ int result = 0;
+
+ // Keep looping, reading a message out of the queue, until we timeout
+ // or get a message with a length == 0, which signals us to quit.
+
+ for (;;)
+ {
+ ACE_Message_Block *mb;
+
+ ACE_Time_Value timeout (ACE_OS::time (0) + 4, 0); // Wait for upto 4 seconds
+
+ result = msg_queue->dequeue_head (mb, &timeout);
+
+ if (result == -1)
+ break;
+
+ int length = mb->length ();
+
+ if (length > 0)
+ ACE_OS::write (ACE_STDOUT, mb->rd_ptr (), length);
+
+ mb->release ();
+
+ if (length == 0)
+ break;
+ }
+
+ if (result == -1 && errno == EWOULDBLOCK)
+ ACE_ERROR ((LM_ERROR,
+ "(%t) %p\n%a",
+ "timed out waiting for message",
+ 1));
+ return 0;
+}
+
+// Spawn off two threads that copy stdin to stdout.
+
+int
+ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ // Message list.
+ ACE_Message_Queue<ACE_MT_SYNCH> msg_queue;
+
+ if (ACE_Thread_Manager::instance ()->spawn
+ (ACE_THR_FUNC (producer),
+ (void *) &msg_queue,
+ THR_NEW_LWP | THR_DETACHED) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%p\n",
+ "spawn"),
+ 1);
+ else if (ACE_Thread_Manager::instance ()->spawn
+ (ACE_THR_FUNC (consumer),
+ (void *) &msg_queue,
+ THR_NEW_LWP | THR_DETACHED) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%p\n",
+ "spawn"),
+ 1);
+
+ // Wait for producer and consumer threads to exit.
+ ACE_Thread_Manager::instance ()->wait ();
+ return 0;
+}
+#else
+int
+ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ ACE_ERROR ((LM_ERROR, "threads not supported on this platform\n"));
+ return 0;
+}
+#endif /* ACE_HAS_THREADS */
diff --git a/ACE/examples/ASX/Message_Queue/buffer_stream.cpp b/ACE/examples/ASX/Message_Queue/buffer_stream.cpp
new file mode 100644
index 00000000000..b1f918cfef5
--- /dev/null
+++ b/ACE/examples/ASX/Message_Queue/buffer_stream.cpp
@@ -0,0 +1,311 @@
+// $Id$
+
+// This short program copies stdin to stdout via the use of an ASX
+// Stream. It illustrates an implementation of the classic "bounded
+// buffer" program using an ASX Stream containing two Modules. Each
+// ACE_Module contains two Tasks. Each ACE_Task contains a
+// ACE_Message_Queue and a pointer to a ACE_Thread_Manager. Note how
+// the use of these reusable components reduces the reliance on global
+// variables, as compared with the bounded_buffer.C example.
+
+#include "ace/OS_main.h"
+#include "ace/OS_NS_stdio.h"
+#include "ace/OS_NS_string.h"
+#include "ace/OS_NS_time.h"
+#include "ace/OS_NS_unistd.h"
+#include "ace/Service_Config.h"
+#include "ace/Stream.h"
+#include "ace/Module.h"
+#include "ace/Task.h"
+
+ACE_RCSID(Message_Queue, buffer_stream, "$Id$")
+
+#if defined (ACE_HAS_THREADS)
+
+typedef ACE_Stream<ACE_MT_SYNCH> MT_Stream;
+typedef ACE_Module<ACE_MT_SYNCH> MT_Module;
+typedef ACE_Task<ACE_MT_SYNCH> MT_Task;
+
+class Common_Task : public MT_Task
+ // = TITLE
+ // Methods that are common to the producer and consumer.
+{
+public:
+ Common_Task (void) {}
+ // ACE_Task hooks
+ virtual int open (void * = 0);
+ virtual int close (u_long = 0);
+};
+
+// Define the Producer interface.
+
+class Producer : public Common_Task
+{
+public:
+ Producer (void) {}
+
+ // Read data from stdin and pass to consumer.
+ virtual int svc (void);
+};
+
+class Consumer : public Common_Task
+ // = TITLE
+ // Define the Consumer interface.
+{
+public:
+ Consumer (void) {}
+
+ virtual int put (ACE_Message_Block *mb,
+ ACE_Time_Value *tv = 0);
+ // Enqueue the message on the ACE_Message_Queue for subsequent
+ // handling in the svc() method.
+
+ virtual int svc (void);
+ // Receive message from producer and print to stdout.
+
+private:
+
+ ACE_Time_Value timeout_;
+};
+
+class Filter : public MT_Task
+ // = TITLE
+ // Defines a Filter that prepends a line number in front of each
+ // line.
+{
+public:
+ Filter (void): count_ (1) {}
+
+ virtual int put (ACE_Message_Block *mb,
+ ACE_Time_Value *tv = 0);
+ // Change the size of the message before passing it downstream.
+
+private:
+ size_t count_;
+ // Count the number of lines passing through the filter.
+};
+
+// Spawn off a new thread.
+
+int
+Common_Task::open (void *)
+{
+ if (this->activate (THR_NEW_LWP | THR_DETACHED) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("spawn")),
+ -1);
+ return 0;
+}
+
+int
+Common_Task::close (u_long exit_status)
+{
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("(%t) thread is exiting with status %d in module %s\n"),
+ exit_status,
+ this->name ()));
+
+ // Can do anything here that is required when a thread exits, e.g.,
+ // storing thread-specific information in some other storage
+ // location, etc.
+ return 0;
+}
+
+// The Consumer reads data from the stdin stream, creates a message,
+// and then queues the message in the message list, where it is
+// removed by the consumer thread. A 0-sized message is enqueued when
+// there is no more data to read. The consumer uses this as a flag to
+// know when to exit.
+
+int
+Producer::svc (void)
+{
+ // Keep reading stdin, until we reach EOF.
+
+ for (int n; ; )
+ {
+ // Allocate a new message (add one to avoid nasty boundary
+ // conditions).
+
+ ACE_Message_Block *mb = 0;
+
+ ACE_NEW_RETURN (mb,
+ ACE_Message_Block (BUFSIZ + 1),
+ -1);
+
+ n = ACE_OS::read (ACE_STDIN, mb->wr_ptr (), BUFSIZ);
+
+ if (n <= 0)
+ {
+ // Send a shutdown message to the other thread and exit.
+ mb->length (0);
+
+ if (this->put_next (mb) == -1)
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("(%t) %p\n"),
+ ACE_TEXT ("put_next")));
+ break;
+ }
+
+ // Send the message to the other thread.
+ else
+ {
+ mb->wr_ptr (n);
+ // NUL-terminate the string (since we use strlen() on it
+ // later).
+ mb->rd_ptr ()[n] = '\0';
+
+ if (this->put_next (mb) == -1)
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("(%t) %p\n"),
+ ACE_TEXT ("put_next")));
+ }
+ }
+
+ return 0;
+}
+
+// Simply enqueue the Message_Block into the end of the queue.
+
+int
+Consumer::put (ACE_Message_Block *mb, ACE_Time_Value *tv)
+{
+ return this->putq (mb, tv);
+}
+
+// The consumer dequeues a message from the ACE_Message_Queue, writes
+// the message to the stderr stream, and deletes the message. The
+// Consumer sends a 0-sized message to inform the consumer to stop
+// reading and exit.
+
+int
+Consumer::svc (void)
+{
+ int result = 0;
+
+ // Keep looping, reading a message out of the queue, until we
+ // timeout or get a message with a length == 0, which signals us to
+ // quit.
+
+ for (;;)
+ {
+ ACE_Message_Block *mb = 0;
+
+ // Wait for upto 4 seconds.
+ this->timeout_.sec (ACE_OS::time (0) + 4);
+
+ result = this->getq (mb, &this->timeout_);
+
+ if (result == -1)
+ break;
+
+ int length = mb->length ();
+
+ if (length > 0)
+ ACE_OS::write (ACE_STDOUT,
+ mb->rd_ptr (),
+ ACE_OS::strlen (mb->rd_ptr ()));
+
+ mb->release ();
+
+ if (length == 0)
+ break;
+ }
+
+ if (result == -1 && errno == EWOULDBLOCK)
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("(%t) %p\n%a"),
+ ACE_TEXT ("timed out waiting for message"),
+ 1));
+ return 0;
+}
+
+int
+Filter::put (ACE_Message_Block *mb,
+ ACE_Time_Value *tv)
+{
+ if (mb->length () == 0)
+ return this->put_next (mb, tv);
+ else
+ {
+ char buf[BUFSIZ];
+
+ // Stash a copy of the buffer away.
+ ACE_OS::strncpy (buf, mb->rd_ptr (), sizeof buf);
+
+ // Increase the size of the buffer large enough that it will be
+ // reallocated (in order to test the reallocation mechanisms).
+
+ mb->size (mb->length () + BUFSIZ);
+ mb->length (mb->size ());
+
+ // Prepend the line count in front of the buffer.
+ ACE_OS::sprintf (mb->rd_ptr (),
+ ACE_SIZE_T_FORMAT_SPECIFIER
+ ": %s",
+ this->count_++,
+ buf);
+ return this->put_next (mb, tv);
+ }
+}
+
+// Main driver function.
+
+int
+ACE_TMAIN (int, ACE_TCHAR *argv[])
+{
+ ACE_Service_Config daemon (argv[0]);
+
+ // This Stream controls hierachically-related active objects.
+ MT_Stream stream;
+
+ MT_Module *pm = 0;
+ MT_Module *fm = 0;
+ MT_Module *cm = 0;
+
+ ACE_NEW_RETURN (cm,
+ MT_Module (ACE_TEXT ("Consumer"),
+ new Consumer),
+ -1);
+ ACE_NEW_RETURN (fm,
+ MT_Module (ACE_TEXT ("Filter"),
+ new Filter),
+ -1);
+ ACE_NEW_RETURN (pm,
+ MT_Module (ACE_TEXT ("Producer"),
+ new Producer),
+ -1);
+
+ // Create Consumer, Filter, and Producer Modules and push them onto
+ // the Stream. All processing is performed in the Stream.
+
+ if (stream.push (cm) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("push")),
+ 1);
+ else if (stream.push (fm) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("push")),
+ 1);
+ else if (stream.push (pm) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("push")),
+ 1);
+ // Barrier synchronization: wait for the threads to exit, then exit
+ // ourselves.
+ ACE_Thread_Manager::instance ()->wait ();
+ return 0;
+}
+#else
+int
+main (int, char *[])
+{
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("threads not supported on this platform\n")));
+ return 0;
+}
+#endif /* ACE_HAS_THREADS */
diff --git a/ACE/examples/ASX/Message_Queue/priority_buffer.cpp b/ACE/examples/ASX/Message_Queue/priority_buffer.cpp
new file mode 100644
index 00000000000..db60a33bcae
--- /dev/null
+++ b/ACE/examples/ASX/Message_Queue/priority_buffer.cpp
@@ -0,0 +1,145 @@
+// $Id$
+
+// This short program prints the contents of stdin to stdout sorted by
+// the length of each line via the use of an ASX Message_Queue. It
+// illustrates how priorities can be used for ACE Message_Queues.
+
+#include "ace/OS_NS_stdio.h"
+#include "ace/Malloc_Base.h" // To get ACE_Allocator
+#include "ace/Message_Queue.h"
+#include "ace/Read_Buffer.h"
+#include "ace/Thread_Manager.h"
+#include "ace/Service_Config.h"
+
+ACE_RCSID(Message_Queue, priority_buffer, "$Id$")
+
+#if defined (ACE_HAS_THREADS)
+
+// Global thread manager.
+static ACE_Thread_Manager thr_mgr;
+
+// Make the queue be capable of being *very* large.
+static const long max_queue = LONG_MAX;
+
+// The consumer dequeues a message from the ACE_Message_Queue, writes
+// the message to the stderr stream, and deletes the message. The
+// producer sends a 0-sized message to inform the consumer to stop
+// reading and exit.
+
+static void *
+consumer (ACE_Message_Queue<ACE_MT_SYNCH> *msg_queue)
+{
+ // Keep looping, reading a message out of the queue, until we
+ // timeout or get a message with a length == 0, which signals us to
+ // quit.
+
+ for (;;)
+ {
+ ACE_Message_Block *mb;
+
+ if (msg_queue->dequeue_head (mb) == -1)
+ break;
+
+ int length = mb->length ();
+
+ if (length > 0)
+ ACE_OS::puts (mb->rd_ptr ());
+
+ // Free up the buffer memory and the Message_Block.
+ ACE_Allocator::instance ()->free (mb->rd_ptr ());
+ mb->release ();
+
+ if (length == 0)
+ break;
+ }
+
+ return 0;
+}
+
+// The producer reads data from the stdin stream, creates a message,
+// and then queues the message in the message list, where it is
+// removed by the consumer thread. A 0-sized message is enqueued when
+// there is no more data to read. The consumer uses this as a flag to
+// know when to exit.
+
+static void *
+producer (ACE_Message_Queue<ACE_MT_SYNCH> *msg_queue)
+{
+ ACE_Read_Buffer rb (ACE_STDIN);
+
+ // Keep reading stdin, until we reach EOF.
+
+ for (;;)
+ {
+ // Allocate a new buffer.
+ char *buffer = rb.read ('\n');
+
+ ACE_Message_Block *mb;
+
+ if (buffer == 0)
+ {
+ // Send a 0-sized shutdown message to the other thread and
+ // exit.
+
+ ACE_NEW_RETURN (mb, ACE_Message_Block ((size_t) 0), 0);
+
+ if (msg_queue->enqueue_tail (mb) == -1)
+ ACE_ERROR ((LM_ERROR, "(%t) %p\n", "put_next"));
+ break;
+ }
+
+ // Enqueue the message in priority order.
+ else
+ {
+ // Allocate a new message, but have it "borrow" its memory
+ // from the buffer.
+ ACE_NEW_RETURN (mb, ACE_Message_Block (rb.size (),
+ ACE_Message_Block::MB_DATA,
+ 0,
+ buffer),
+ 0);
+ mb->msg_priority (rb.size ());
+ mb->wr_ptr (rb.size ());
+
+ ACE_DEBUG ((LM_DEBUG,
+ "enqueueing message of size %d\n",
+ mb->msg_priority ()));
+
+ // Enqueue in priority order.
+ if (msg_queue->enqueue_prio (mb) == -1)
+ ACE_ERROR ((LM_ERROR, "(%t) %p\n", "put_next"));
+ }
+ }
+
+ // Now read all the items out in priority order (i.e., ordered by
+ // the size of the lines!).
+ consumer (msg_queue);
+
+ return 0;
+}
+
+// Spawn off one thread that copies stdin to stdout in order of the
+// size of each line.
+
+int
+ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ // Message queue.
+ ACE_Message_Queue<ACE_MT_SYNCH> msg_queue (max_queue);
+
+ if (thr_mgr.spawn (ACE_THR_FUNC (producer), (void *) &msg_queue,
+ THR_NEW_LWP | THR_DETACHED) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "spawn"), 1);
+
+ // Wait for producer and consumer threads to exit.
+ thr_mgr.wait ();
+ return 0;
+}
+#else
+int
+ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ ACE_ERROR ((LM_ERROR, "threads not supported on this platform\n"));
+ return 0;
+}
+#endif /* ACE_HAS_THREADS */
diff --git a/ACE/examples/ASX/UPIPE_Event_Server/Consumer_Router.cpp b/ACE/examples/ASX/UPIPE_Event_Server/Consumer_Router.cpp
new file mode 100644
index 00000000000..b9c9c0cf2bd
--- /dev/null
+++ b/ACE/examples/ASX/UPIPE_Event_Server/Consumer_Router.cpp
@@ -0,0 +1,138 @@
+// $Id$
+
+#include "ace/OS_NS_stdio.h"
+#include "ace/OS_NS_string.h"
+#include "Consumer_Router.h"
+#include "Options.h"
+
+ACE_RCSID(UPIPE_Event_Server, Consumer_Router, "$Id$")
+
+#if defined (ACE_HAS_THREADS)
+
+typedef Acceptor_Factory<Consumer_Handler, CONSUMER_KEY> CONSUMER_FACTORY;
+
+int
+Consumer_Handler::open (void *a)
+{
+ CONSUMER_FACTORY *af = (CONSUMER_FACTORY *) a;
+ this->router_task_ = af->router ();
+ return this->Peer_Handler<CONSUMER_ROUTER, CONSUMER_KEY>::open (a);
+}
+
+Consumer_Handler::Consumer_Handler (ACE_Thread_Manager *tm)
+ : Peer_Handler<CONSUMER_ROUTER, CONSUMER_KEY> (tm)
+{
+}
+
+// Create a new handler that will interact with a consumer and point
+// its ROUTER_TASK_ data member to the CONSUMER_ROUTER.
+
+Consumer_Router::Consumer_Router (ACE_Thread_Manager *tm)
+ : CONSUMER_ROUTER (tm)
+{
+}
+
+// Initialize the Router..
+
+int
+Consumer_Router::open (void *)
+{
+ ACE_ASSERT (this->is_reader ());
+ ACE_TCHAR *argv[3];
+
+ argv[0] = (ACE_TCHAR *) this->name ();
+ argv[1] = (ACE_TCHAR *) options.consumer_file ();
+ argv[2] = 0;
+
+ if (this->init (1, &argv[1]) == -1)
+ return -1;
+
+ // Make this an active object.
+ // return this->activate (options.t_flags ());
+
+ // Until that's done, return 1 to indicate that the object wasn't activated.
+ return 1;
+}
+
+int
+Consumer_Router::close (u_long)
+{
+ ACE_ASSERT (this->is_reader ());
+ this->peer_map_.close ();
+ this->msg_queue ()->deactivate();
+ return 0;
+}
+
+
+// Handle incoming messages in a separate thread..
+
+int
+Consumer_Router::svc (void)
+{
+ ACE_Message_Block *mb = 0;
+
+ ACE_ASSERT (this->is_reader ());
+
+ if (options.debug ())
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("(%t) starting svc in %s\n"),
+ this->name ()));
+
+ while (this->getq (mb) > 0)
+ if (this->put_next (mb) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("(%t) put_next failed in %s\n"),
+ this->name ()), -1);
+
+ return 0;
+ // Note the implicit ACE_OS::thr_exit() via destructor.
+}
+
+// Send a MESSAGE_BLOCK to the supplier(s)..
+
+int
+Consumer_Router::put (ACE_Message_Block *mb, ACE_Time_Value *)
+{
+ ACE_ASSERT (this->is_reader ());
+
+ if (mb->msg_type () == ACE_Message_Block::MB_IOCTL)
+ {
+ this->control (mb);
+ return this->put_next (mb);
+ }
+ else
+{
+//printf("consumer-Router is routing : send_peers\n");
+ return this->send_peers (mb);
+}
+}
+
+// Return information about the Client_Router ACE_Module..
+
+int
+Consumer_Router::info (ACE_TCHAR **strp, size_t length) const
+{
+ ACE_TCHAR buf[BUFSIZ];
+ ACE_UPIPE_Addr addr;
+ const ACE_TCHAR *mod_name = this->name ();
+ ACE_UPIPE_Acceptor &sa = (ACE_UPIPE_Acceptor &) *this->acceptor_;
+
+ if (sa.get_local_addr (addr) == -1)
+ return -1;
+
+#if !defined (ACE_WIN32) && defined (ACE_USES_WCHAR)
+# define FMTSTR ACE_TEXT ("%ls\t %ls/ %ls")
+#else
+# define FMTSTR ACE_TEXT ("%s\t %s/ %s")
+#endif
+
+ ACE_OS::sprintf (buf, FMTSTR,
+ mod_name, ACE_TEXT ("upipe"),
+ ACE_TEXT ("# consumer router\n"));
+
+ if (*strp == 0 && (*strp = ACE_OS::strdup (mod_name)) == 0)
+ return -1;
+ else
+ ACE_OS::strncpy (*strp, mod_name, length);
+ return ACE_OS::strlen (mod_name);
+}
+
+#endif /* ACE_HAS_THREADS */
diff --git a/ACE/examples/ASX/UPIPE_Event_Server/Consumer_Router.h b/ACE/examples/ASX/UPIPE_Event_Server/Consumer_Router.h
new file mode 100644
index 00000000000..93a1220dc11
--- /dev/null
+++ b/ACE/examples/ASX/UPIPE_Event_Server/Consumer_Router.h
@@ -0,0 +1,53 @@
+/* -*- C++ -*- */
+// $Id$
+
+// The interface between one or more consumers and an Event Server
+// ACE_Stream.
+
+#ifndef _CONSUMER_ROUTER_H
+#define _CONSUMER_ROUTER_H
+
+#include "ace/Thread_Manager.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/UPIPE_Acceptor.h"
+#include "ace/UPIPE_Addr.h"
+#include "ace/Svc_Handler.h"
+#include "Peer_Router.h"
+
+#if defined (ACE_HAS_THREADS)
+
+class Consumer_Handler; // Forward declaration....
+
+typedef ACE_HANDLE CONSUMER_KEY;
+
+typedef Peer_Router<Consumer_Handler, CONSUMER_KEY> CONSUMER_ROUTER;
+
+class Consumer_Handler
+ : public Peer_Handler<CONSUMER_ROUTER, CONSUMER_KEY>
+{
+public:
+ Consumer_Handler (ACE_Thread_Manager *tm = 0);
+ virtual int open (void *);
+};
+
+class Consumer_Router : public CONSUMER_ROUTER
+{
+public:
+ Consumer_Router (ACE_Thread_Manager *thr_manager);
+
+protected:
+ // ACE_Task hooks..
+ virtual int open (void *a = 0);
+ virtual int close (u_long flags = 0);
+ virtual int put (ACE_Message_Block *msg, ACE_Time_Value * = 0);
+ virtual int svc (void);
+
+ // Dynamic linking hooks.
+ virtual int info (ACE_TCHAR **info_string, size_t length) const;
+};
+#endif /* ACE_HAS_THREADS */
+#endif /* _CONSUMER_ROUTER_H */
diff --git a/ACE/examples/ASX/UPIPE_Event_Server/Event_Analyzer.cpp b/ACE/examples/ASX/UPIPE_Event_Server/Event_Analyzer.cpp
new file mode 100644
index 00000000000..689a9280766
--- /dev/null
+++ b/ACE/examples/ASX/UPIPE_Event_Server/Event_Analyzer.cpp
@@ -0,0 +1,73 @@
+// $Id$
+
+#include "ace/OS_NS_string.h"
+#include "Event_Analyzer.h"
+
+ACE_RCSID(UPIPE_Event_Server, Event_Analyzer, "$Id$")
+
+#if defined (ACE_HAS_THREADS)
+
+int
+Event_Analyzer::open (void *)
+{
+ return 0;
+}
+
+int
+Event_Analyzer::close (u_long)
+{
+ return 0;
+}
+
+int
+Event_Analyzer::control (ACE_Message_Block *mb)
+{
+ ACE_IO_Cntl_Msg *ioc = (ACE_IO_Cntl_Msg *) mb->rd_ptr ();
+ ACE_IO_Cntl_Msg::ACE_IO_Cntl_Cmds cmd;
+
+ switch (cmd = ioc->cmd ())
+ {
+ case ACE_IO_Cntl_Msg::SET_LWM:
+ case ACE_IO_Cntl_Msg::SET_HWM:
+ this->water_marks (cmd, *(size_t *) mb->cont ()->rd_ptr ());
+ break;
+ default:
+ break;
+ }
+ return 0;
+}
+
+int
+Event_Analyzer::put (ACE_Message_Block *mb, ACE_Time_Value *)
+{
+ if (mb->msg_type () == ACE_Message_Block::MB_IOCTL)
+ this->control (mb);
+
+ return this->put_next (mb);
+}
+
+int
+Event_Analyzer::init (int, ACE_TCHAR *[])
+{
+ return 0;
+}
+
+int
+Event_Analyzer::fini (void)
+{
+ return 0;
+}
+
+int
+Event_Analyzer::info (ACE_TCHAR **strp, size_t length) const
+{
+ const ACE_TCHAR *mod_name = this->name ();
+
+ if (*strp == 0 && (*strp = ACE_OS::strdup (mod_name)) == 0)
+ return -1;
+ else
+ ACE_OS::strncpy (*strp, mod_name, length);
+ return ACE_OS::strlen (mod_name);
+}
+
+#endif /* ACE_HAS_THREADS */
diff --git a/ACE/examples/ASX/UPIPE_Event_Server/Event_Analyzer.h b/ACE/examples/ASX/UPIPE_Event_Server/Event_Analyzer.h
new file mode 100644
index 00000000000..01bc3028964
--- /dev/null
+++ b/ACE/examples/ASX/UPIPE_Event_Server/Event_Analyzer.h
@@ -0,0 +1,37 @@
+/* -*- C++ -*- */
+// $Id$
+
+// Signal router.
+
+#ifndef _EVENT_ANALYZER_H
+#define _EVENT_ANALYZER_H
+
+#include "ace/Stream.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/Module.h"
+#include "ace/Task.h"
+
+#if defined (ACE_HAS_THREADS)
+
+class Event_Analyzer : public ACE_Task<ACE_MT_SYNCH>
+{
+public:
+ virtual int open (void *a = 0);
+ virtual int close (u_long flags = 0);
+ virtual int put (ACE_Message_Block *msg, ACE_Time_Value * = 0);
+
+ // Dynamic linking hooks.
+ virtual int init (int argc, ACE_TCHAR *argv[]);
+ virtual int fini (void);
+ virtual int info (ACE_TCHAR **info_string, size_t length) const;
+
+private:
+ virtual int control (ACE_Message_Block *);
+};
+
+#endif /* ACE_HAS_THREADS */
+#endif /* _EVENT_ANALYZER_H */
diff --git a/ACE/examples/ASX/UPIPE_Event_Server/Makefile.am b/ACE/examples/ASX/UPIPE_Event_Server/Makefile.am
new file mode 100644
index 00000000000..ff730184cba
--- /dev/null
+++ b/ACE/examples/ASX/UPIPE_Event_Server/Makefile.am
@@ -0,0 +1,49 @@
+## Process this file with automake to create Makefile.in
+##
+## $Id$
+##
+## This file was generated by MPC. Any changes made directly to
+## this file will be lost the next time it is generated.
+##
+## MPC Command:
+## /acebuilds/ACE_wrappers-repository/bin/mwc.pl -include /acebuilds/MPC/config -include /acebuilds/MPC/templates -feature_file /acebuilds/ACE_wrappers-repository/local.features -noreldefs -type automake -exclude build,Kokyu
+
+ACE_BUILDDIR = $(top_builddir)
+ACE_ROOT = $(top_srcdir)
+
+
+## Makefile.UPIPE_Event_Server.am
+
+if !BUILD_ACE_FOR_TAO
+noinst_PROGRAMS = UPIPE_Event_Server
+
+UPIPE_Event_Server_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+UPIPE_Event_Server_SOURCES = \
+ Consumer_Router.cpp \
+ Event_Analyzer.cpp \
+ Options.cpp \
+ Peer_Router.cpp \
+ Supplier_Router.cpp \
+ event_server.cpp \
+ Consumer_Router.h \
+ Event_Analyzer.h \
+ Options.h \
+ Options.i \
+ Peer_Router.h \
+ Supplier_Router.h
+
+UPIPE_Event_Server_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+endif !BUILD_ACE_FOR_TAO
+
+## Clean up template repositories, etc.
+clean-local:
+ -rm -f *~ *.bak *.rpo *.sym lib*.*_pure_* core core.*
+ -rm -f gcctemp.c gcctemp so_locations *.ics
+ -rm -rf cxx_repository ptrepository ti_files
+ -rm -rf templateregistry ir.out
+ -rm -rf ptrepository SunWS_cache Templates.DB
diff --git a/ACE/examples/ASX/UPIPE_Event_Server/Options.cpp b/ACE/examples/ASX/UPIPE_Event_Server/Options.cpp
new file mode 100644
index 00000000000..ca2cbbca887
--- /dev/null
+++ b/ACE/examples/ASX/UPIPE_Event_Server/Options.cpp
@@ -0,0 +1,207 @@
+// $Id$
+
+#include "ace/Get_Opt.h"
+#include "ace/Log_Msg.h"
+#include "ace/OS_NS_Thread.h"
+#include "ace/OS_NS_stdio.h"
+#if defined (ACE_HAS_TRACE)
+# include "ace/OS_NS_strings.h"
+#endif /* ACE_HAS_TRACE */
+
+#include "Options.h"
+
+ACE_RCSID(UPIPE_Event_Server, Options, "$Id$")
+
+#if defined (ACE_HAS_THREADS)
+
+Options::Options (void)
+ : thr_count_ (4),
+ t_flags_ (THR_DETACHED),
+ high_water_mark_ (8 * 1024),
+ low_water_mark_ (1024),
+ message_size_ (128),
+ initial_queue_length_ (0),
+ iterations_ (100000),
+ debugging_ (0),
+ verbosity_ (0),
+ consumer_port_ (ACE_TEXT ("-p 10000")),
+ supplier_port_ (ACE_TEXT ("-p 10001")),
+ consumer_file_ (ACE_TEXT ("-f/tmp/conupipe")),
+ supplier_file_ (ACE_TEXT ("-f/tmp/supupipe"))
+{
+}
+
+Options::~Options (void)
+{
+}
+
+void Options::print_results (void)
+{
+ ACE_Profile_Timer::ACE_Elapsed_Time et;
+ this->itimer_.elapsed_time (et);
+
+#if defined (ACE_HAS_PRUSAGE_T)
+ prusage_t rusage;
+ this->itimer_.get_rusage (rusage);
+
+ if (options.verbose ())
+ {
+ ACE_OS::printf ("final concurrency hint = %d\n", ACE_OS::thr_getconcurrency ());
+ ACE_OS::printf ("%8d = lwpid\n"
+ "%8d = lwp count\n"
+ "%8d = minor page faults\n"
+ "%8d = major page faults\n"
+ "%8d = input blocks\n"
+ "%8d = output blocks\n"
+ "%8d = messages sent\n"
+ "%8d = messages received\n"
+ "%8d = signals received\n"
+ "%8ds, %dms = wait-cpu (latency) time\n"
+ "%8ds, %dms = user lock wait sleep time\n"
+ "%8ds, %dms = all other sleep time\n"
+ "%8d = voluntary context switches\n"
+ "%8d = involuntary context switches\n"
+ "%8d = system calls\n"
+ "%8d = chars read/written\n",
+ (int) rusage.pr_lwpid,
+ (int) rusage.pr_count,
+ (int) rusage.pr_minf,
+ (int) rusage.pr_majf,
+ (int) rusage.pr_inblk,
+ (int) rusage.pr_oublk,
+ (int) rusage.pr_msnd,
+ (int) rusage.pr_mrcv,
+ (int) rusage.pr_sigs,
+ (int) rusage.pr_wtime.tv_sec, (int) rusage.pr_wtime.tv_nsec / 1000000,
+ (int) rusage.pr_ltime.tv_sec, (int) rusage.pr_ltime.tv_nsec / 1000000,
+ (int) rusage.pr_slptime.tv_sec, (int) rusage.pr_slptime.tv_nsec / 1000000,
+ (int) rusage.pr_vctx,
+ (int) rusage.pr_ictx,
+ (int) rusage.pr_sysc,
+ (int) rusage.pr_ioch);
+ }
+#endif /* ACE_HAS_PRUSAGE_T */
+
+ ACE_OS::printf ("---------------------\n"
+ "real time = %.3f\n"
+ "user time = %.3f\n"
+ "system time = %.3f\n"
+ "---------------------\n",
+ et.real_time, et.user_time, et.system_time);
+}
+
+// Manages the options.
+Options options;
+
+void
+Options::parse_args (int argc, ACE_TCHAR *argv[])
+{
+ ACE_LOG_MSG->open (argv[0]);
+
+ ACE_Get_Opt getopt (argc, argv, ACE_TEXT ("C:c:bdH:i:L:l:M:nS:s:t:T:v"));
+ int c;
+
+ while ((c = getopt ()) != -1)
+ switch (c)
+ {
+ case 'b':
+ this->t_flags (THR_BOUND);
+ break;
+ case 'C':
+ this->consumer_file (getopt.opt_arg ());
+ break;
+ case 'c':
+ this->consumer_port (getopt.opt_arg ());
+ break;
+ case 'd':
+ this->debugging_ = 1;
+ break;
+ case 'H':
+ this->high_water_mark (ACE_OS::atoi (getopt.opt_arg ()));
+ break;
+ case 'i':
+ this->iterations (ACE_OS::atoi (getopt.opt_arg ()));
+ break;
+ case 'L':
+ this->low_water_mark (ACE_OS::atoi (getopt.opt_arg ()));
+ break;
+ case 'l':
+ this->initial_queue_length (ACE_OS::atoi (getopt.opt_arg ()));
+ break;
+ case 'M':
+ this->message_size (ACE_OS::atoi (getopt.opt_arg ()));
+ break;
+ case 'n':
+ this->t_flags (THR_NEW_LWP);
+ break;
+ case 'S':
+ this->supplier_file (getopt.opt_arg ());
+ break;
+ case 's':
+ this->supplier_port (getopt.opt_arg ());
+ break;
+ case 'T':
+#if defined (ACE_HAS_TRACE)
+ if (ACE_OS::strcasecmp (getopt.opt_arg (), ACE_TEXT ("ON")) == 0)
+ ACE_Trace::start_tracing ();
+ else if (ACE_OS::strcasecmp (getopt.opt_arg (), ACE_TEXT ("OFF")) == 0)
+ ACE_Trace::stop_tracing ();
+#endif /* ACE_HAS_TRACE */
+ break;
+ case 't':
+ this->thr_count (ACE_OS::atoi (getopt.opt_arg ()));
+ break;
+ case 'v':
+ this->verbosity_ = 1;
+ break;
+ default:
+ ::fprintf (stderr, "%s\n"
+ "\t[-b] (THR_BOUND)\n"
+ "\t[-C consumer file]\n"
+ "\t[-c consumer port]\n"
+ "\t[-d] (enable debugging)\n"
+ "\t[-H high water mark]\n"
+ "\t[-i number of test iterations]\n"
+ "\t[-L low water mark]\n"
+ "\t[-M] message size \n"
+ "\t[-n] (THR_NEW_LWP)\n"
+ "\t[-q max queue size]\n"
+ "\t[-S supplier file]\n"
+ "\t[-s supplier port]\n"
+ "\t[-t number of threads]\n"
+ "\t[-v] (verbose) \n",
+ ACE_TEXT_ALWAYS_CHAR (argv[0]));
+ ::exit (1);
+ /* NOTREACHED */
+ break;
+ }
+
+ // HACK! This needs to be done to avoid the mismatch from ACE_LIB_TEXT
+ // in ACE_SIZE_T_FORMAT_SPECIFIER to narrow-char on wide-char builds.
+ // It only works because it's at the end of the file.
+# if defined (ACE_LIB_TEXT)
+# undef ACE_LIB_TEXT
+# endif
+# define ACE_LIB_TEXT(X) X
+ if (this->verbose ())
+ ACE_OS::printf ("%8d = initial concurrency hint\n"
+ ACE_SIZE_T_FORMAT_SPECIFIER " = total iterations\n"
+ ACE_SIZE_T_FORMAT_SPECIFIER " = thread count\n"
+ ACE_SIZE_T_FORMAT_SPECIFIER " = low water mark\n"
+ ACE_SIZE_T_FORMAT_SPECIFIER " = high water mark\n"
+ ACE_SIZE_T_FORMAT_SPECIFIER " = message_size\n"
+ ACE_SIZE_T_FORMAT_SPECIFIER " = initial queue length\n"
+ "%8d = THR_BOUND\n"
+ "%8d = THR_NEW_LWP\n",
+ ACE_OS::thr_getconcurrency (),
+ this->iterations (),
+ this->thr_count (),
+ this->low_water_mark (),
+ this->high_water_mark (),
+ this->message_size (),
+ this->initial_queue_length (),
+ (this->t_flags () & THR_BOUND) != 0,
+ (this->t_flags () & THR_NEW_LWP) != 0);
+}
+
+#endif /* ACE_HAS_THREADS */
diff --git a/ACE/examples/ASX/UPIPE_Event_Server/Options.h b/ACE/examples/ASX/UPIPE_Event_Server/Options.h
new file mode 100644
index 00000000000..1acad4b9d1f
--- /dev/null
+++ b/ACE/examples/ASX/UPIPE_Event_Server/Options.h
@@ -0,0 +1,88 @@
+/* -*- C++ -*- */
+// $Id$
+
+// Option manager for Event Server.
+
+#ifndef DEVICE_OPTIONS_H
+#define DEVICE_OPTIONS_H
+
+#include "ace/config-all.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/Profile_Timer.h"
+
+#if defined (ACE_HAS_THREADS)
+
+class Options
+{
+public:
+ Options (void);
+ ~Options (void);
+ void parse_args (int argc, ACE_TCHAR *argv[]);
+
+ void stop_timer (void);
+ void start_timer (void);
+
+ void thr_count (size_t count);
+ size_t thr_count (void);
+
+ void initial_queue_length (size_t length);
+ size_t initial_queue_length (void);
+
+ void high_water_mark (size_t size);
+ size_t high_water_mark (void);
+
+ void low_water_mark (size_t size);
+ size_t low_water_mark (void);
+
+ void message_size (size_t size);
+ size_t message_size (void);
+
+ void iterations (size_t n);
+ size_t iterations (void);
+
+ void t_flags (long flag);
+ long t_flags (void);
+
+ void supplier_port (const ACE_TCHAR *port);
+ const ACE_TCHAR *supplier_port (void);
+
+ void consumer_port (const ACE_TCHAR *port);
+ const ACE_TCHAR *consumer_port (void);
+
+ void supplier_file (const ACE_TCHAR *file);
+ const ACE_TCHAR *supplier_file (void);
+
+ void consumer_file (const ACE_TCHAR *file);
+ const ACE_TCHAR *consumer_file (void);
+
+ int debug (void);
+ int verbose (void);
+
+ void print_results (void);
+
+private:
+ ACE_Profile_Timer itimer_; // Time the process.
+ size_t thr_count_; // Number of threads to spawn.
+ long t_flags_; // Flags to thr_create().
+ size_t high_water_mark_; // ACE_Task high water mark.
+ size_t low_water_mark_; // ACE_Task low water mark.
+ size_t message_size_; // Size of a message.
+ size_t initial_queue_length_; // Initial number of items in the queue.
+ size_t iterations_; // Number of iterations to run the test program.
+ int debugging_; // Extra debugging info.
+ int verbosity_; // Extra verbose messages.
+ const ACE_TCHAR *consumer_port_; // Port that the Consumer_Router is using.
+ const ACE_TCHAR *supplier_port_; // Port that the Supplier_Router is using.
+ const ACE_TCHAR *consumer_file_; // file that the Consumer_Router is using.
+ const ACE_TCHAR *supplier_file_; // file that the Supplier_Router is using.
+};
+
+extern Options options;
+
+#include "Options.i"
+#endif /* ACE_HAS_THREADS */
+#endif /* DEVICE_OPTIONS_H */
diff --git a/ACE/examples/ASX/UPIPE_Event_Server/Options.i b/ACE/examples/ASX/UPIPE_Event_Server/Options.i
new file mode 100644
index 00000000000..af04f73eb26
--- /dev/null
+++ b/ACE/examples/ASX/UPIPE_Event_Server/Options.i
@@ -0,0 +1,166 @@
+/* -*- C++ -*- */
+// $Id$
+
+// Option manager for ustreams.
+
+// Since this is only included in Options.h these should stay
+// inline, not ACE_INLINE.
+// FUZZ: disable check_for_inline
+
+
+inline void
+Options::supplier_port (const ACE_TCHAR *port)
+{
+ this->supplier_port_ = port;
+}
+
+inline const ACE_TCHAR *
+Options::supplier_port (void)
+{
+ return this->supplier_port_;
+}
+
+inline void
+Options::supplier_file (const ACE_TCHAR *file)
+{
+ this->supplier_file_ = file;
+}
+
+inline const ACE_TCHAR *
+Options::supplier_file (void)
+{
+ return this->supplier_file_;
+}
+
+inline void
+Options::consumer_file (const ACE_TCHAR *file)
+{
+ this->consumer_file_ = file;
+}
+
+inline const ACE_TCHAR *
+Options::consumer_file (void)
+{
+ return this->consumer_file_;
+}
+
+inline void
+Options::consumer_port (const ACE_TCHAR *port)
+{
+ this->consumer_port_ = port;
+}
+
+inline const ACE_TCHAR *
+Options::consumer_port (void)
+{
+ return this->consumer_port_;
+}
+
+inline void
+Options::start_timer (void)
+{
+ this->itimer_.start ();
+}
+
+inline void
+Options::stop_timer (void)
+{
+ this->itimer_.stop ();
+}
+
+inline void
+Options::thr_count (size_t count)
+{
+ this->thr_count_ = count;
+}
+
+inline size_t
+Options::thr_count (void)
+{
+ return this->thr_count_;
+}
+
+inline void
+Options::initial_queue_length (size_t length)
+{
+ this->initial_queue_length_ = length;
+}
+
+inline size_t
+Options::initial_queue_length (void)
+{
+ return this->initial_queue_length_;
+}
+
+inline void
+Options::high_water_mark (size_t size)
+{
+ this->high_water_mark_ = size;
+}
+
+inline size_t
+Options::high_water_mark (void)
+{
+ return this->high_water_mark_;
+}
+
+inline void
+Options::low_water_mark (size_t size)
+{
+ this->low_water_mark_ = size;
+}
+
+inline size_t
+Options::low_water_mark (void)
+{
+ return this->low_water_mark_;
+}
+
+inline void
+Options::message_size (size_t size)
+{
+ this->message_size_ = size;
+}
+
+inline size_t
+Options::message_size (void)
+{
+ return this->message_size_;
+}
+
+inline void
+Options::iterations (size_t n)
+{
+ this->iterations_ = n;
+}
+
+inline size_t
+Options::iterations (void)
+{
+ return this->iterations_;
+}
+
+inline void
+Options::t_flags (long flag)
+{
+ this->t_flags_ |= flag;
+}
+
+inline long
+Options::t_flags (void)
+{
+ return this->t_flags_;
+}
+
+inline int
+Options::debug (void)
+{
+ return this->debugging_;
+}
+
+inline int
+Options::verbose (void)
+{
+ return this->verbosity_;
+}
+
diff --git a/ACE/examples/ASX/UPIPE_Event_Server/Peer_Router.cpp b/ACE/examples/ASX/UPIPE_Event_Server/Peer_Router.cpp
new file mode 100644
index 00000000000..757eecedc33
--- /dev/null
+++ b/ACE/examples/ASX/UPIPE_Event_Server/Peer_Router.cpp
@@ -0,0 +1,283 @@
+// $Id$
+
+#if !defined (_PEER_ROUTER_C)
+
+#define _PEER_ROUTER_C
+
+#include "ace/Get_Opt.h"
+#include "ace/Service_Config.h"
+
+#include "Peer_Router.h"
+#include "Options.h"
+
+ACE_RCSID(UPIPE_Event_Server, Peer_Router, "$Id$")
+
+#if defined (ACE_HAS_THREADS)
+
+// Define some short-hand macros to deal with long templates
+// names...
+
+#define PH PEER_HANDLER
+#define PA PEER_ACCEPTOR
+#define PAD PEER_ADDR
+#define PK PEER_KEY
+#define PM PEER_MAP
+
+template <class PH, class PK> int
+Acceptor_Factory<PH, PK>::init (int argc, ACE_TCHAR *argv[])
+{
+ ACE_Get_Opt get_opt (argc, argv, ACE_TEXT ("df:"), 0);
+ ACE_UPIPE_Addr addr;
+
+ for (int c; (c = get_opt ()) != -1; )
+ switch (c)
+ {
+ case 'f':
+ addr.set (get_opt.opt_arg ());
+ break;
+ case 'd':
+ break;
+ default:
+ break;
+ }
+
+ if (this->open (addr, ACE_Reactor::instance ()) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("%p\n"), ACE_TEXT ("open")), -1);
+ return 0;
+}
+
+template <class PH, class PK>
+Acceptor_Factory<PH, PK>::Acceptor_Factory (Peer_Router<PH, PK> *pr)
+ : pr_ (pr)
+{
+}
+
+template <class PH, class PK> Peer_Router<PH, PK> *
+Acceptor_Factory<PH, PK>::router (void)
+{
+ return this->pr_;
+}
+
+template <class ROUTER, class KEY>
+Peer_Handler<ROUTER, KEY>::Peer_Handler (ACE_Thread_Manager *tm)
+ : ACE_Svc_Handler<ACE_UPIPE_STREAM, ACE_MT_SYNCH> (tm)
+{
+}
+
+template <class ROUTER, class KEY> int
+Peer_Handler<ROUTER, KEY>::svc (void)
+{
+ // Just a try !! we're just reading from our ACE_Message_Queue.
+ ACE_Message_Block *db, *hb;
+ int n;
+ // do an endless loop
+ for (;;)
+ {
+ db = new ACE_Message_Block (BUFSIZ);
+ hb = new ACE_Message_Block (sizeof (KEY), ACE_Message_Block::MB_PROTO, db);
+
+ if ((n = this->peer ().recv (db->rd_ptr (), db->size ())) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("%p\n"),
+ ACE_TEXT ("recv failed")), -1);
+ else if (n == 0) // Client has closed down the connection.
+ {
+
+ if (this->router_task_->unbind_peer (this->get_handle ()) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("%p\n"),
+ ACE_TEXT ("unbind failed")), -1);
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("(%t) shutting down \n")));
+ return -1; // We do not need to be deregistered by reactor
+ // as we were not registered at all
+ }
+ else // Transform incoming buffer into a Message and pass downstream.
+ {
+ db->wr_ptr (n);
+ *(ACE_HANDLE *) hb->rd_ptr () = this->get_handle (); // structure assignment.
+ hb->wr_ptr (sizeof (long));
+ if (this->router_task_->reply (hb) == -1)
+ {
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Peer_Handler.svc : router_task->reply failed\n")));
+ return -1;
+ }
+
+ // return this->router_task_->reply (hb) == -1 ? -1 : 0;
+ }
+ }
+ ACE_NOTREACHED(return 0);
+}
+
+template <class ROUTER, class KEY> int
+Peer_Handler<ROUTER, KEY>::put (ACE_Message_Block *mb, ACE_Time_Value *)
+{
+ return this->peer ().send_n (mb->rd_ptr (), mb->length ());
+}
+
+// Create a new handler and point its ROUTER_TASK_ data member to the
+// corresponding router. Note that this router is extracted out of
+// the Acceptor_Factory * that is passed in via the
+// ACE_Acceptor::handle_input() method.
+
+template <class ROUTER, class KEY> int
+Peer_Handler<ROUTER, KEY>::open (void *a)
+{
+ ACE_TCHAR buf[BUFSIZ], *p = buf;
+
+ if (this->router_task_->info (&p, sizeof buf) != -1)
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("(%t) creating handler for %s, fd = %d, this = %@\n"),
+ buf, this->get_handle (), a));
+ else
+ ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("%p\n"), ACE_TEXT ("info")), -1);
+
+ if ( this->activate (options.t_flags ()) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("%p\n"),
+ ACE_TEXT ("activation of thread failed")), -1);
+ else if (this->router_task_->bind_peer (this->get_handle (), this) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("%p\n"),
+ ACE_TEXT ("bind_peer")), -1);
+ return 0;
+}
+
+// Receive a message from a supplier..
+
+template <class ROUTER, class KEY> int
+Peer_Handler<ROUTER, KEY>::handle_input (ACE_HANDLE h)
+{
+
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("(%t) input arrived on sd %d\n"), h));
+// ACE_Reactor::instance ()->remove_handler(h,
+// ACE_Event_Handler::ALL_EVENTS_MASK
+// |ACE_Event_Handler::DONT_CALL);
+// this method should be called only if the peer shuts down
+// so we deactivate our ACE_Message_Queue to awake our svc thread
+
+ return 0;
+
+#if 0
+ ACE_Message_Block *db = new ACE_Message_Block (BUFSIZ);
+ ACE_Message_Block *hb = new ACE_Message_Block (sizeof (KEY), ACE_Message_Block::MB_PROTO, db);
+ int n;
+
+ if ((n = this->peer ().recv (db->rd_ptr (), db->size ())) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("%p\n"), ACE_TEXT ("recv failed")), -1);
+ else if (n == 0) // Client has closed down the connection.
+ {
+ if (this->router_task_->unbind_peer (this->get_handle ()) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("%p\n"),
+ ACE_TEXT ("unbind failed")), -1);
+ ACE_DEBUG ((LM_DEBUG, "(%t) shutting down %d\n", h));
+ return -1; // Instruct the ACE_Reactor to deregister us by returning -1.
+ }
+ else // Transform incoming buffer into a Message and pass downstream.
+ {
+ db->wr_ptr (n);
+ *(long *) hb->rd_ptr () = this->get_handle (); // structure assignment.
+ hb->wr_ptr (sizeof (long));
+ return this->router_task_->reply (hb) == -1 ? -1 : 0;
+ }
+#endif
+}
+
+template <class PH, class PK>
+Peer_Router<PH, PK>::Peer_Router (ACE_Thread_Manager *tm)
+ : ACE_Task<ACE_MT_SYNCH> (tm)
+{
+}
+
+template <class PH, class PK> int
+Peer_Router<PH, PK>::send_peers (ACE_Message_Block *mb)
+{
+ ACE_Map_Iterator<PK, PH *, ACE_RW_Mutex> map_iter = this->peer_map_;
+ int bytes = 0;
+ int iterations = 0;
+ ACE_Message_Block *data_block = mb->cont ();
+ for (ACE_Map_Entry<PK, PH *> *ss = 0;
+ map_iter.next (ss) != 0;
+ map_iter.advance ())
+ {
+ if (options.debug ())
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("(%t) sending to peer via sd %d\n"),
+ ss->ext_id_));
+
+ iterations++;
+ bytes += ss->int_id_->put (data_block);
+ }
+
+ mb->release ();
+ return bytes == 0 ? 0 : bytes / iterations;
+}
+
+template <class PH, class PK>
+Peer_Router<PH, PK>::~Peer_Router (void)
+{
+}
+
+template <class PH, class PK> int
+Peer_Router<PH, PK>::fini (void)
+{
+ delete this->acceptor_;
+ return 0;
+}
+
+template <class PH, class PK> int
+Peer_Router<PH, PK>::control (ACE_Message_Block *mb)
+{
+ ACE_IO_Cntl_Msg *ioc = (ACE_IO_Cntl_Msg *) mb->rd_ptr ();
+ ACE_IO_Cntl_Msg::ACE_IO_Cntl_Cmds command;
+
+ switch (command = ioc->cmd ())
+ {
+ case ACE_IO_Cntl_Msg::SET_LWM:
+ case ACE_IO_Cntl_Msg::SET_HWM:
+ this->water_marks (command, *(size_t *) mb->cont ()->rd_ptr ());
+ break;
+ default:
+ return -1;
+ }
+ return 0;
+}
+
+template <class PH, class PK> int
+Peer_Router<PH, PK>::unbind_peer (PK key)
+{
+ return this->peer_map_.unbind (key);
+}
+
+template <class PH, class PK> int
+Peer_Router<PH, PK>::bind_peer (PK key, Peer_Handler<Peer_Router<PH, PK>, PK> *ph)
+{
+ PH *peer_handler = (PH *) ph;
+ return this->peer_map_.bind (key, peer_handler);
+}
+
+template <class PH, class PK> int
+Peer_Router<PH, PK>::init (int argc, ACE_TCHAR *argv[])
+{
+ this->acceptor_ = new Acceptor_Factory <PH, PK> (this);
+
+ if (this->acceptor_->init (argc, argv) == -1
+ || this->peer_map_.open () == -1)
+ return -1;
+ else
+ {
+ ACE_UPIPE_Addr addr;
+ ACE_UPIPE_Acceptor &pa = this->acceptor_->acceptor ();
+
+ if (pa.get_local_addr (addr) != -1)
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("(%t) initializing %s, file = %s, fd = %d, this = %@\n"),
+ this->name (), addr.get_path_name (), pa.get_handle (), this));
+ else
+ ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("%p\n"),
+ ACE_TEXT ("get_local_addr")), -1);
+ }
+ return 0;
+}
+
+#undef PH
+#undef PA
+#undef PAD
+#undef PK
+#undef PM
+#endif /* ACE_HAS_THREADS */
+#endif /* _PEER_ROUTER_C */
diff --git a/ACE/examples/ASX/UPIPE_Event_Server/Peer_Router.h b/ACE/examples/ASX/UPIPE_Event_Server/Peer_Router.h
new file mode 100644
index 00000000000..3962d371ae0
--- /dev/null
+++ b/ACE/examples/ASX/UPIPE_Event_Server/Peer_Router.h
@@ -0,0 +1,127 @@
+/* -*- C++ -*- */
+// $Id$
+
+// The interface between one or more peers and a stream. A peer
+// typically runs remotely on another machine.
+
+#ifndef _PEER_ROUTER_H
+#define _PEER_ROUTER_H
+
+#include "ace/Acceptor.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/Svc_Handler.h"
+#include "ace/UPIPE_Acceptor.h"
+#include "ace/UPIPE_Addr.h"
+#include "ace/Thread_Manager.h"
+#include "ace/Map_Manager.h"
+
+#if defined (ACE_HAS_THREADS)
+#include "ace/RW_Mutex.h"
+
+// Forward declaration.
+template <class PEER_HANDLER, class KEY>
+class Peer_Router;
+
+template <class PEER_HANDLER, class KEY>
+class Acceptor_Factory : public ACE_Acceptor<PEER_HANDLER, ACE_UPIPE_ACCEPTOR>
+{
+public:
+ Acceptor_Factory (Peer_Router<PEER_HANDLER, KEY> *pr);
+ Peer_Router<PEER_HANDLER, KEY> *router (void);
+
+ int init (int argc, ACE_TCHAR *argv[]);
+ // Initialize the acceptor when it's linked dynamically.
+
+private:
+ Peer_Router<PEER_HANDLER, KEY> *pr_;
+};
+
+// Receive input from a Peer..
+template <class ROUTER, class KEY>
+class Peer_Handler : public ACE_Svc_Handler<ACE_UPIPE_STREAM, ACE_MT_SYNCH>
+{
+public:
+ Peer_Handler (ACE_Thread_Manager * = 0);
+
+ virtual int open (void * = 0);
+ // Called by the ACE_Acceptor::handle_input() to activate this object.
+
+ virtual int handle_input (ACE_HANDLE);
+ // Receive input from the peer..
+
+ virtual int put (ACE_Message_Block *, ACE_Time_Value *tv = 0);
+ // Send output to a peer.
+
+protected:
+ ROUTER *router_task_;
+ // Pointer to write task..
+
+private:
+ // Don't need this method here...
+ virtual int svc (void);
+};
+
+// This abstract base class provides mechanisms for routing messages
+// to/from a ACE_Stream from/to one or more peers (which are typically
+// running on remote hosts). A subclass of Peer_Router overrides the
+// open(), close(), and put() methods in order to specialize the
+// behavior of the router to meet application-specific requirements.
+
+template <class PEER_HANDLER, class PEER_KEY>
+class Peer_Router : public ACE_Task<ACE_MT_SYNCH>
+{
+public:
+ Peer_Router (ACE_Thread_Manager * = 0);
+ ~Peer_Router (void);
+
+ typedef Peer_Handler<Peer_Router<PEER_HANDLER, PEER_KEY>, PEER_KEY> HANDLER;
+
+ // Remove a PEER_HANDLER from the PEER_MAP.
+ virtual int unbind_peer (PEER_KEY);
+
+ // Add a PEER_HANDLER to the PEER_MAP.
+ virtual int bind_peer (PEER_KEY, HANDLER *);
+
+ // Send the message block to the peer(s)..
+ int send_peers (ACE_Message_Block *mb);
+
+protected:
+// Handle control messages arriving from adjacent Modules.
+ virtual int control (ACE_Message_Block *);
+
+ // Map used to keep track of active peers.
+ ACE_Map_Manager <PEER_KEY, PEER_HANDLER *, ACE_RW_Mutex> peer_map_;
+
+ // Dynamic linking initialization hooks inherited from ACE_Task.
+ virtual int init (int argc, ACE_TCHAR *argv[]);
+ virtual int fini (void);
+
+ // Factory for accepting new PEER_HANDLERs.
+ Acceptor_Factory<PEER_HANDLER, PEER_KEY> *acceptor_;
+
+private:
+// Prevent copies and pass-by-value.
+ ACE_UNIMPLEMENTED_FUNC (Peer_Router (const Peer_Router<PEER_HANDLER, PEER_KEY> &))
+ ACE_UNIMPLEMENTED_FUNC (void operator= (const Peer_Router<PEER_HANDLER, PEER_KEY> &))
+};
+
+#if defined (__ACE_INLINE__)
+#define ACE_INLINE inline
+#else
+#define ACE_INLINE
+#endif /* __ACE_INLINE__ */
+
+#if defined (ACE_TEMPLATES_REQUIRE_SOURCE)
+#include "Peer_Router.cpp"
+#endif /* ACE_TEMPLATES_REQUIRE_SOURCE */
+
+#if defined (ACE_TEMPLATES_REQUIRE_PRAGMA)
+#pragma implementation ("Peer_Router.cpp")
+#endif /* ACE_TEMPLATES_REQUIRE_PRAGMA */
+
+#endif /* ACE_HAS_THREADS */
+#endif /* _PEER_ROUTER_H */
diff --git a/ACE/examples/ASX/UPIPE_Event_Server/Supplier_Router.cpp b/ACE/examples/ASX/UPIPE_Event_Server/Supplier_Router.cpp
new file mode 100644
index 00000000000..8b4a53d6331
--- /dev/null
+++ b/ACE/examples/ASX/UPIPE_Event_Server/Supplier_Router.cpp
@@ -0,0 +1,137 @@
+// $Id$
+
+#include "ace/OS_NS_stdio.h"
+#include "ace/OS_NS_string.h"
+#include "Options.h"
+#include "Supplier_Router.h"
+
+ACE_RCSID(UPIPE_Event_Server, Supplier_Router, "$Id$")
+
+#if defined (ACE_HAS_THREADS)
+
+typedef Acceptor_Factory<Supplier_Handler, SUPPLIER_KEY> SUPPLIER_FACTORY;
+
+int
+Supplier_Handler::open (void *a)
+{
+ SUPPLIER_FACTORY *af = (SUPPLIER_FACTORY *) a;
+ this->router_task_ = af->router ();
+ return this->Peer_Handler<SUPPLIER_ROUTER, SUPPLIER_KEY>::open (a);
+}
+
+Supplier_Handler::Supplier_Handler (ACE_Thread_Manager *tm)
+ : Peer_Handler<SUPPLIER_ROUTER, SUPPLIER_KEY> (tm)
+{
+}
+
+// Create a new router and associate it with the REACTOR parameter..
+
+Supplier_Router::Supplier_Router (ACE_Thread_Manager *tm)
+ : SUPPLIER_ROUTER (tm)
+{
+}
+
+// Handle incoming messages in a separate thread..
+
+int
+Supplier_Router::svc (void)
+{
+ ACE_ASSERT (this->is_writer ());
+
+ ACE_Message_Block *message_block = 0;
+
+ if (options.debug ())
+ ACE_DEBUG ((LM_DEBUG, "(%t) starting svc in %s\n", this->name ()));
+
+ while (this->getq (message_block) > 0)
+ {
+ if (this->put_next (message_block) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, "(%t) put_next failed in %s\n", this->name ()), -1);
+ }
+
+ return 0;
+}
+
+// Initialize the Router..
+
+int
+Supplier_Router::open (void *)
+{
+ ACE_ASSERT (this->is_writer ());
+ ACE_TCHAR *argv[3];
+
+ argv[0] = (ACE_TCHAR *)this->name ();
+ argv[1] = (ACE_TCHAR *)options.supplier_file ();
+ argv[2] = 0;
+
+ if (this->init (1, &argv[1]) == -1)
+ return -1;
+
+ // Make this an active object.
+ // return this->activate (options.t_flags ());
+
+ // Until that's done, return 1 to indicate that the object wasn't activated.
+ return 1;
+}
+
+// Close down the router..
+
+int
+Supplier_Router::close (u_long)
+{
+ ACE_ASSERT (this->is_writer ());
+ this->peer_map_.close ();
+ this->msg_queue ()->deactivate();
+ return 0;
+}
+
+// Send a MESSAGE_BLOCK to the supplier(s)..
+
+int
+Supplier_Router::put (ACE_Message_Block *mb, ACE_Time_Value *)
+{
+ ACE_ASSERT (this->is_writer ());
+
+ if (mb->msg_type () == ACE_Message_Block::MB_IOCTL)
+ {
+ this->control (mb);
+ return this->put_next (mb);
+ }
+ else
+ {
+//printf("supplier-Router is routing: send_peers\n");
+ return this->send_peers (mb);
+ }
+}
+
+// Return information about the Supplier_Router ACE_Module..
+
+int
+Supplier_Router::info (ACE_TCHAR **strp, size_t length) const
+{
+ ACE_TCHAR buf[BUFSIZ];
+ ACE_UPIPE_Addr addr;
+ const ACE_TCHAR *mod_name = this->name ();
+ ACE_UPIPE_Acceptor &sa = (ACE_UPIPE_Acceptor &) *this->acceptor_;
+
+ if (sa.get_local_addr (addr) == -1)
+ return -1;
+
+#if !defined (ACE_WIN32) && defined (ACE_USES_WCHAR)
+# define FMTSTR ACE_TEXT ("%ls\t %ls/ %ls")
+#else
+# define FMTSTR ACE_TEXT ("%s\t %s/ %s")
+#endif
+
+ ACE_OS::sprintf (buf, FMTSTR,
+ mod_name, ACE_TEXT ("upipe"),
+ ACE_TEXT ("# supplier router\n"));
+
+ if (*strp == 0 && (*strp = ACE_OS::strdup (mod_name)) == 0)
+ return -1;
+ else
+ ACE_OS::strncpy (*strp, mod_name, length);
+ return ACE_OS::strlen (mod_name);
+}
+
+#endif /* ACE_HAS_THREADS */
diff --git a/ACE/examples/ASX/UPIPE_Event_Server/Supplier_Router.h b/ACE/examples/ASX/UPIPE_Event_Server/Supplier_Router.h
new file mode 100644
index 00000000000..4d5d440e018
--- /dev/null
+++ b/ACE/examples/ASX/UPIPE_Event_Server/Supplier_Router.h
@@ -0,0 +1,57 @@
+/* -*- C++ -*- */
+// $Id$
+
+// The interface between a supplier and an Event Service ACE_Stream.
+
+#ifndef _SUPPLIER_ROUTER_H
+#define _SUPPLIER_ROUTER_H
+
+#include "ace/UPIPE_Addr.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/UPIPE_Acceptor.h"
+#include "ace/Map_Manager.h"
+#include "ace/Svc_Handler.h"
+#include "Peer_Router.h"
+
+#if defined (ACE_HAS_THREADS)
+
+// Forward declaration.
+class Supplier_Handler;
+
+// Type of search key for SUPPLIER_MAP.
+typedef ACE_HANDLE SUPPLIER_KEY;
+
+// Instantiated type for routing messages to suppliers.
+
+typedef Peer_Router<Supplier_Handler, SUPPLIER_KEY> SUPPLIER_ROUTER;
+
+class Supplier_Handler
+ : public Peer_Handler<SUPPLIER_ROUTER, SUPPLIER_KEY>
+{
+public:
+ Supplier_Handler (ACE_Thread_Manager *tm = 0);
+ virtual int open (void *);
+};
+
+class Supplier_Router : public SUPPLIER_ROUTER
+{
+public:
+ Supplier_Router (ACE_Thread_Manager *);
+
+protected:
+ // ACE_Task hooks..
+ virtual int open (void *a = 0);
+ virtual int close (u_long flags = 0);
+ virtual int put (ACE_Message_Block *msg, ACE_Time_Value * = 0);
+ virtual int svc (void);
+
+ // Dynamic linking hooks inherited from Peer_Router.
+ virtual int info (ACE_TCHAR **info_string, size_t length) const;
+};
+
+#endif /* ACE_HAS_THREADS */
+#endif /* _SUPPLIER_ROUTER_H */
diff --git a/ACE/examples/ASX/UPIPE_Event_Server/UPIPE_Event.mpc b/ACE/examples/ASX/UPIPE_Event_Server/UPIPE_Event.mpc
new file mode 100644
index 00000000000..a4c93dc1fdb
--- /dev/null
+++ b/ACE/examples/ASX/UPIPE_Event_Server/UPIPE_Event.mpc
@@ -0,0 +1,15 @@
+// -*- MPC -*-
+// $Id$
+
+project(*Server) : aceexe {
+ avoids += ace_for_tao
+ exename = UPIPE_Event_Server
+ Source_Files {
+ Consumer_Router.cpp
+ Event_Analyzer.cpp
+ Options.cpp
+ Peer_Router.cpp
+ Supplier_Router.cpp
+ event_server.cpp
+ }
+}
diff --git a/ACE/examples/ASX/UPIPE_Event_Server/event_server.cpp b/ACE/examples/ASX/UPIPE_Event_Server/event_server.cpp
new file mode 100644
index 00000000000..e1d5b8c440d
--- /dev/null
+++ b/ACE/examples/ASX/UPIPE_Event_Server/event_server.cpp
@@ -0,0 +1,269 @@
+// $Id$
+
+// Test the event server.
+
+#include "ace/OS_main.h"
+#include "ace/Stream.h"
+#include "ace/Service_Config.h"
+#include "ace/UPIPE_Acceptor.h"
+#include "ace/UPIPE_Connector.h"
+
+// FUZZ: disable check_for_streams_include
+#include "ace/streams.h"
+
+#include "Options.h"
+#include "Consumer_Router.h"
+#include "Event_Analyzer.h"
+#include "Supplier_Router.h"
+#include "ace/Sig_Adapter.h"
+#include "ace/OS_NS_unistd.h"
+
+ACE_RCSID (UPIPE_Event_Server,
+ event_server,
+ "$Id$")
+
+#if defined (ACE_HAS_THREADS)
+
+typedef ACE_Stream<ACE_MT_SYNCH> MT_Stream;
+typedef ACE_Module<ACE_MT_SYNCH> MT_Module;
+
+// Handle SIGINT and terminate the entire application.
+
+class Quit_Handler : public ACE_Sig_Adapter
+{
+public:
+ Quit_Handler (void);
+ virtual int handle_input (ACE_HANDLE fd);
+};
+
+Quit_Handler::Quit_Handler (void)
+ : ACE_Sig_Adapter (ACE_Sig_Handler_Ex (ACE_Reactor::end_event_loop))
+{
+ // Register to trap input from the user.
+ if (ACE_Event_Handler::register_stdin_handler (this,
+ ACE_Reactor::instance (),
+ ACE_Thread_Manager::instance ()) == -1)
+ ACE_ERROR ((LM_ERROR, "%p\n", "register_stdin_handler"));
+ // Register to trap the SIGINT signal.
+ else if (ACE_Reactor::instance ()->register_handler
+ (SIGINT, this) == -1)
+ ACE_ERROR ((LM_ERROR, "%p\n", "register_handler"));
+}
+
+int
+Quit_Handler::handle_input (ACE_HANDLE)
+{
+ options.stop_timer ();
+ ACE_DEBUG ((LM_INFO, " (%t) closing down the test\n"));
+ options.print_results ();
+
+ ACE_Reactor::end_event_loop();
+ return 0;
+}
+
+static void *
+consumer (void *)
+{
+ ACE_UPIPE_Stream c_stream;
+ ACE_UPIPE_Addr c_addr (ACE_TEXT ("/tmp/conupipe"));
+
+ int verb = options.verbose ();
+ int msiz = options.message_size ();
+ int secs, par1, par2;
+ time_t currsec;
+
+ if (verb)
+ cout << "consumer starting connect" << endl;
+
+ ACE_UPIPE_Connector con;
+
+ if (con.connect (c_stream, c_addr) == -1)
+ ACE_DEBUG ((LM_INFO, " (%t) connect failed\n"));
+ else
+ cout << "consumer :we're connected" << endl;
+
+ ACE_Message_Block *mb_p;
+
+ int done = 0;
+ int cnt = 0;
+ ACE_OS::time (&currsec);
+
+ par1= (time_t) currsec;
+
+ while (done == 0
+ && (c_stream.recv (mb_p) != -1))
+ if (mb_p->length () > 1)
+ {
+ cnt++;
+ if (verb)
+ cout << " consumer received message !!!!!! "
+ << mb_p->rd_ptr () << endl;
+ }
+ else
+ {
+ if (verb)
+ cout << "consumer got last mb"
+ << (char) * (mb_p->rd_ptr ()) << endl;
+ c_stream.close ();
+ done = 1;
+ }
+
+ ACE_OS::time (&currsec);
+ par2 = (time_t) currsec;
+
+ secs = par2 - par1;
+
+ if (secs <= 0)
+ secs=1;
+
+ cout << "consumer got " << cnt << " messages of size " << msiz
+ << "within " << secs << " seconds" << endl;
+
+ ACE_OS::sleep (2);
+ cout << "consumer terminating " << endl;
+ return 0;
+}
+
+static void *
+supplier (void *dummy)
+{
+ ACE_UPIPE_Stream s_stream;
+ ACE_UPIPE_Addr serv_addr (ACE_TEXT ("/tmp/supupipe"));
+ ACE_UPIPE_Connector con;
+
+ int iter = options.iterations ();
+ int verb = options.verbose ();
+ int msiz = options.message_size ();
+ cout << "supplier starting connect" << endl;
+
+ if (con.connect (s_stream, serv_addr) == -1)
+ ACE_DEBUG ((LM_INFO, " (%t) connect failed\n"));
+
+ cout << "supplier : we're connected" << endl;
+ int n;
+ n = 0;
+ ACE_Message_Block * mb_p;
+
+ while (n < iter)
+ {
+ mb_p = new ACE_Message_Block (msiz);
+ strcpy (mb_p->rd_ptr (), (char *) dummy);
+ mb_p->length (msiz);
+ if (verb)
+ cout << "supplier sending 1 message_block" << endl;
+ if (s_stream.send (mb_p) == -1)
+ {
+ cout << "supplier send failed" << endl;
+ return (void *) -1;
+ }
+ n++;
+ }
+
+ mb_p = new ACE_Message_Block (10);
+ mb_p->length (1);
+ *mb_p->rd_ptr () = 'g';
+
+ cout << "supplier sending last message_block" << endl;
+
+ if (s_stream.send (mb_p) == -1)
+ {
+ cout << "supplier send last mb failed" << endl;
+ return (void *) -1;
+ }
+ mb_p = new ACE_Message_Block (10);
+ mb_p->length (0);
+
+ if (verb)
+ cout << "supplier sending very last message_block" << endl;
+
+ if (s_stream.send (mb_p) == -1)
+ {
+ cout << "supplier send very last mb failed" << endl;
+ return (void *) -1;
+ }
+
+ ACE_OS::sleep (2);
+ cout << "supplier terminating" << endl;
+ return 0;
+}
+
+int
+ACE_TMAIN (int argc, ACE_TCHAR *argv[])
+{
+ ACE_Service_Config daemon;
+
+ options.parse_args (argc, argv);
+ options.start_timer ();
+
+ // Primary ACE_Stream for EVENT_SERVER application.
+ MT_Stream event_server;
+
+ // Enable graceful shutdowns....
+ Quit_Handler quit_handler;
+
+ // Create the modules..
+
+ MT_Module *sr = new MT_Module (ACE_TEXT ("Supplier_Router"),
+ new Supplier_Router (ACE_Thread_Manager::instance ()));
+ MT_Module *ea = new MT_Module (ACE_TEXT ("Event_Analyzer"),
+ new Event_Analyzer,
+ new Event_Analyzer);
+ MT_Module *cr = new MT_Module (ACE_TEXT ("Consumer_Router"),
+ 0, // 0 triggers the creation of a ACE_Thru_Task...
+ new Consumer_Router (ACE_Thread_Manager::instance ()));
+
+ // Push the modules onto the event_server stream.
+
+ if (event_server.push (sr) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("%p\n"),
+ ACE_TEXT ("push (Supplier_Router)")), -1);
+
+ if (event_server.push (ea) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("%p\n"),
+ ACE_TEXT ("push (Event_Analyzer)")), -1);
+
+ if (event_server.push (cr) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("%p\n"),
+ ACE_TEXT ("push (Consumer_Router)")), -1);
+
+ // Set the high and low water marks appropriately.
+
+ int wm = options.low_water_mark ();
+
+ if (event_server.control (ACE_IO_Cntl_Msg::SET_LWM, &wm) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("%p\n"),
+ ACE_TEXT ("push (setting low watermark)")), -1);
+
+ wm = options.high_water_mark ();
+ if (event_server.control (ACE_IO_Cntl_Msg::SET_HWM, &wm) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("%p\n"),
+ ACE_TEXT ("push (setting high watermark)")), -1);
+
+ // spawn the two threads.
+
+ if (ACE_Thread_Manager::instance ()->spawn (ACE_THR_FUNC (consumer), (void *) 0,
+ THR_NEW_LWP | THR_DETACHED) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("%p\n"), ACE_TEXT ("spawn")), 1);
+
+ else if (ACE_Thread_Manager::instance ()->spawn (ACE_THR_FUNC (supplier), (void *) "hello",
+ THR_NEW_LWP | THR_DETACHED) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("%p\n"), ACE_TEXT ("spawn")), 1);
+
+ // Perform the main event loop waiting for the user to type ^C or to
+ // enter a line on the ACE_STDIN.
+
+ ACE_Reactor::instance ()->run_reactor_event_loop ();
+
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("main exiting\n")));
+
+ return 0;
+}
+#else
+int
+ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("test not defined for this platform\n")),
+ -1);
+}
+#endif /* ACE_HAS_THREADS */
diff --git a/ACE/examples/Bounded_Packet_Relay/.cvsignore b/ACE/examples/Bounded_Packet_Relay/.cvsignore
new file mode 100644
index 00000000000..2f50e8efaee
--- /dev/null
+++ b/ACE/examples/Bounded_Packet_Relay/.cvsignore
@@ -0,0 +1,2 @@
+bpr_thread
+bpr_thread
diff --git a/ACE/examples/Bounded_Packet_Relay/BPR_Drivers.cpp b/ACE/examples/Bounded_Packet_Relay/BPR_Drivers.cpp
new file mode 100644
index 00000000000..fb646962004
--- /dev/null
+++ b/ACE/examples/Bounded_Packet_Relay/BPR_Drivers.cpp
@@ -0,0 +1,535 @@
+// $Id$
+
+// ============================================================================
+// = LIBRARY
+// examples
+//
+// = FILENAME
+// BPR_Driver.cpp
+//
+// = DESCRIPTION
+// This code builds an abstraction to factor out common code for
+// the different implementations of the Timer_Queue.
+//
+// = AUTHORS
+// Chris Gill <cdgill@cs.wustl.edu> and
+// Douglas C. Schmidt <schmidt@cs.wustl.edu>
+//
+// Based on the Timer Queue Test example written by
+//
+// Carlos O'Ryan <coryan@cs.wustl.edu> and
+// Douglas C. Schmidt <schmidt@cs.wustl.edu> and
+// Sergio Flores-Gaitan <sergio@cs.wustl.edu>
+//
+// ============================================================================
+
+#include "ace/OS_NS_sys_time.h"
+#include "BPR_Drivers.h"
+
+ACE_RCSID(Bounded_Packet_Relay, BPR_Drivers, "$Id$")
+
+// Constructor.
+
+Input_Device_Wrapper_Base::Input_Device_Wrapper_Base (ACE_Thread_Manager *input_task_mgr)
+ : ACE_Task_Base (input_task_mgr),
+ send_input_msg_cmd_ (0),
+ input_period_ (ACE_ONE_SECOND_IN_USECS),
+ is_active_ (0),
+ send_count_ (0)
+{
+}
+
+// Destructor.
+
+Input_Device_Wrapper_Base::~Input_Device_Wrapper_Base (void)
+{
+}
+
+// Sets send input message command in the input device driver object.
+
+int
+Input_Device_Wrapper_Base::set_send_input_msg_cmd (ACE_Command_Base *send_input_msg_cmd)
+{
+ // Set the new command. Input device is not responsible
+ // for deleting the old command, if any.
+ send_input_msg_cmd_ = send_input_msg_cmd;
+ return 0;
+}
+
+// Sets period between when input messages are produced.
+
+int
+Input_Device_Wrapper_Base::set_input_period (u_long input_period)
+{
+ input_period_ = input_period;
+ return 0;
+}
+
+// Sets count of messages to send.
+
+int
+Input_Device_Wrapper_Base::set_send_count (long count)
+{
+ send_count_ = count;
+ return 0;
+}
+
+// Request that the input device stop sending messages
+// and terminate its thread. Should return 1 if it will do so, 0
+// if it has already done so, or -1 if there is a problem doing so.
+
+int
+Input_Device_Wrapper_Base::request_stop (void)
+{
+ if (is_active_)
+ {
+ is_active_ = 0;
+ return 1;
+ }
+
+ return 0;
+}
+
+// This method runs the input device loop in the new thread.
+
+int
+Input_Device_Wrapper_Base::svc (void)
+{
+ ACE_Time_Value timeout;
+ ACE_Message_Block *message;
+
+ // Set a flag to indicate we're active.
+ is_active_ = 1;
+
+ // Start with the total count of messages to send.
+ for (current_count_ = send_count_;
+ // While we're still marked active, and there are packets to send.
+ (is_active_) && (current_count_ != 0);
+ )
+ {
+ // Create an input message to send.
+ message = create_input_message ();
+ if (message == 0)
+ {
+ if (is_active_)
+ {
+ is_active_ = 0;
+ ACE_ERROR_RETURN ((LM_ERROR, "%t %p\n",
+ "Failed to create input message object"),
+ -1);
+ }
+
+ break;
+ }
+
+ // Make sure there is a send command object.
+ if (send_input_msg_cmd_ == 0)
+ {
+ delete message;
+ if (is_active_)
+ {
+ is_active_ = 0;
+ ACE_ERROR_RETURN ((LM_ERROR, "%t %p\n",
+ "send message command object not instantiated"),
+ -1);
+ }
+
+ break;
+ }
+
+ // Send the input message.
+ if (send_input_msg_cmd_->execute ((void *) message) < 0)
+ {
+ delete message;
+ if (is_active_)
+ {
+ is_active_ = 0;
+ ACE_ERROR_RETURN ((LM_ERROR, "%t %p\n",
+ "Failed executing send message command object"),
+ -1);
+ }
+
+ break;
+ }
+
+ // If all went well, decrement count of messages to send, and
+ // run the reactor event loop unti we get a timeout or something
+ // happens in a registered upcall.
+ if (current_count_ > 0)
+ --current_count_;
+
+ timeout = ACE_Time_Value (0, input_period_);
+ reactor_.run_event_loop (timeout);
+ }
+
+ is_active_ = 0;
+
+ return 0;
+}
+
+// Sends a newly created message block, carrying data read from the
+// underlying input device, by passing a pointer to the message block
+// to its command execution.
+
+int
+Input_Device_Wrapper_Base::send_input_message (ACE_Message_Block *amb)
+{
+ if (send_input_msg_cmd_)
+ return send_input_msg_cmd_->execute ((void *) amb);
+ else
+ {
+ if (is_active_)
+ ACE_ERROR ((LM_ERROR, "%t %p\n",
+ "Input_Device_Wrapper_Base::send_input_message: "
+ "command object not instantiated"));
+
+ return -1;
+ }
+}
+
+Output_Device_Wrapper_Base::~Output_Device_Wrapper_Base (void)
+{
+}
+
+// Constructor.
+
+Bounded_Packet_Relay::Bounded_Packet_Relay (ACE_Thread_Manager *input_task_mgr,
+ Input_Device_Wrapper_Base *input_wrapper,
+ Output_Device_Wrapper_Base *output_wrapper)
+ : is_active_ (0),
+ input_task_mgr_ (input_task_mgr),
+ input_wrapper_ (input_wrapper),
+ output_wrapper_ (output_wrapper),
+ queue_ (Bounded_Packet_Relay::DEFAULT_HWM,
+ Bounded_Packet_Relay::DEFAULT_LWM),
+ queue_hwm_ (Bounded_Packet_Relay::DEFAULT_HWM),
+ queue_lwm_ (Bounded_Packet_Relay::DEFAULT_LWM),
+ transmission_number_ (0),
+ packets_sent_ (0),
+ status_ (Bounded_Packet_Relay::UN_INITIALIZED),
+ transmission_start_ (ACE_Time_Value::zero),
+ transmission_end_ (ACE_Time_Value::zero)
+{
+ if (input_task_mgr_ == 0)
+ input_task_mgr_ = ACE_Thread_Manager::instance ();
+}
+
+// Destructor.
+
+Bounded_Packet_Relay::~Bounded_Packet_Relay (void)
+{
+ // Reactivate the queue, and then clear it.
+ queue_.activate ();
+ while (! queue_.is_empty ())
+ {
+ ACE_Message_Block *msg;
+ queue_.dequeue_head (msg);
+ delete msg;
+ }
+
+}
+
+// Requests output be sent to output device.
+
+int
+Bounded_Packet_Relay::send_input (void)
+{
+ // Don't block, return immediately if queue is empty.
+ ACE_Message_Block *item;
+
+ // Using a separate (non-const) time value
+ // is necessary on some platforms
+ ACE_Time_Value immediate (ACE_Time_Value::zero);
+
+ if (queue_.dequeue_head (item,
+ &immediate) < 0)
+ return 1;
+
+ // If a message block was dequeued, send it to the output device.
+
+ if (output_wrapper_->write_output_message ((void *) item) < 0)
+ {
+ if (is_active_)
+ ACE_ERROR ((LM_ERROR,
+ "%t %p\n",
+ "failed to write to output device object"));
+
+ return -1;
+ }
+
+ // If all went OK, increase count of packets sent.
+ ++packets_sent_;
+ return 0;
+}
+
+// Requests a transmission be started.
+
+int
+Bounded_Packet_Relay::start_transmission (u_long packet_count,
+ u_long arrival_period,
+ int logging_level)
+{
+ // Serialize access to start and end transmission calls, statistics
+ // reporting calls.
+ ACE_GUARD_RETURN (ACE_SYNCH_MUTEX, ace_mon, this->transmission_lock_, -1);
+
+ // If a transmission is already in progress, just return.
+ if (is_active_)
+ return 1;
+
+ // Set transmission in progress flag true.
+ is_active_ = 1;
+
+ // Update statistics for a new transmission.
+ ++transmission_number_;
+ packets_sent_ = 0;
+ status_ = STARTED;
+ transmission_start_ = ACE_OS::gettimeofday ();
+
+ // Reactivate the queue, and then clear it.
+ queue_.activate ();
+ while (! queue_.is_empty ())
+ {
+ ACE_Message_Block *msg;
+ queue_.dequeue_head (msg);
+ delete msg;
+ }
+
+ // Initialize the output device.
+ if (output_wrapper_->modify_device_settings ((void *) &logging_level) < 0)
+ {
+ status_ = ERROR_DETECTED;
+ transmission_end_ = ACE_OS::gettimeofday ();
+ is_active_ = 0;
+ ACE_ERROR_RETURN ((LM_ERROR, "%t %p\n",
+ "failed to initialize output device object"),
+ -1);
+ }
+ // Initialize the input device.
+ if (input_wrapper_->modify_device_settings ((void *) &logging_level) < 0)
+ {
+ status_ = ERROR_DETECTED;
+ transmission_end_ = ACE_OS::gettimeofday ();
+ is_active_ = 0;
+ ACE_ERROR_RETURN ((LM_ERROR, "%t %p\n",
+ "failed to initialize output device object"),
+ -1);
+ }
+ else if (input_wrapper_->set_input_period (arrival_period) < 0)
+ {
+ status_ = ERROR_DETECTED;
+ transmission_end_ = ACE_OS::gettimeofday ();
+ is_active_ = 0;
+ ACE_ERROR_RETURN ((LM_ERROR, "%t %p\n",
+ "failed to initialize input device object"),
+ -1);
+ }
+ else if (input_wrapper_->set_send_count (packet_count) < 0)
+ {
+ status_ = ERROR_DETECTED;
+ transmission_end_ = ACE_OS::gettimeofday ();
+ is_active_ = 0;
+ ACE_ERROR_RETURN ((LM_ERROR, "%t %p\n",
+ "failed to initialize input device object"),
+ -1);
+ }
+ // Activate the input device.
+ else if (input_wrapper_->activate () < 0)
+ {
+ status_ = ERROR_DETECTED;
+ transmission_end_ = ACE_OS::gettimeofday ();
+ is_active_ = 0;
+ ACE_ERROR_RETURN ((LM_ERROR, "%t %p\n",
+ "failed to activate input device object"),
+ -1);
+ }
+
+ // If all went well, print a startup message and return success.
+ ACE_DEBUG ((LM_DEBUG,
+ "\n\nTransmission %u started\n\n",
+ transmission_number_));
+ return 0;
+}
+
+// Requests a transmission be ended.
+
+int
+Bounded_Packet_Relay::end_transmission (Transmission_Status status)
+{
+ // Serialize access to start and end transmission calls,
+ // statistics reporting calls.
+ ACE_GUARD_RETURN (ACE_SYNCH_MUTEX, ace_mon, this->transmission_lock_, -1);
+
+ // If a transmission is not already in progress, just return.
+ if (! is_active_)
+ return 1;
+
+ // Set transmission in progress flag false.
+ is_active_ = 0;
+
+ // Ask the the input thread to stop.
+ if (input_wrapper_->request_stop () < 0)
+ {
+ status_ = ERROR_DETECTED;
+ transmission_end_ = ACE_OS::gettimeofday ();
+ ACE_ERROR_RETURN ((LM_ERROR, "%t %p\n",
+ "failed asking input device thread to stop"),
+ -1);
+ }
+
+ // Deactivate the queue, allowing all waiting threads to continue.
+ queue_.deactivate ();
+
+ // Wait for input thread to stop.
+ input_task_mgr_->wait_task (input_wrapper_);
+
+ // Reactivate the queue, and then clear it.
+ queue_.activate ();
+ while (! queue_.is_empty ())
+ {
+ ACE_Message_Block *msg;
+ queue_.dequeue_head (msg);
+ delete msg;
+ }
+
+ // If all went well, set passed status, stamp end time, print a
+ // termination message, and return success.
+ status_ = status;
+ transmission_end_ = ACE_OS::gettimeofday ();
+ ACE_DEBUG ((LM_DEBUG,
+ "\n\nTransmission %u ended with status: %s\n\n",
+ transmission_number_, status_msg ()));
+ return 0;
+}
+
+// Requests a report of statistics from the last transmission.
+
+int
+Bounded_Packet_Relay::report_statistics (void)
+{
+ // Serialize access to start and end transmission calls,
+ // statistics reporting calls.
+ ACE_GUARD_RETURN (ACE_SYNCH_MUTEX, ace_mon, this->transmission_lock_, -1);
+
+ // If a transmission is already in progress, just return.
+ if (is_active_)
+ return 1;
+
+ // Calculate duration of trasmission.
+ ACE_Time_Value duration (transmission_end_);
+ duration -= transmission_start_;
+
+ // Report transmission statistics.
+ ACE_DEBUG ((LM_DEBUG,
+ "\n\nStatisics for transmission %u:\n\n"
+ "Transmission status: %s\n"
+ "Start time: %d (sec) %d (usec)\n"
+ "End time: %d (sec) %d (usec)\n"
+ "Duration: %d (sec) %d (usec)\n"
+ "Packets relayed: %u\n\n",
+ transmission_number_, status_msg (),
+ transmission_start_.sec (),
+ transmission_start_.usec (),
+ transmission_end_.sec (),
+ transmission_end_.usec (),
+ duration.sec (),
+ duration.usec (),
+ packets_sent_));
+ return 0;
+}
+
+// Public entry point to which to push input.
+
+int
+Bounded_Packet_Relay::receive_input (void * arg)
+{
+ if (! arg)
+ {
+ if (is_active_)
+ ACE_ERROR ((LM_ERROR, "%t %p\n",
+ "Bounded_Packet_Relay::receive_input: "
+ "null argument"));
+
+ return -1;
+ }
+ ACE_Message_Block *message = static_cast<ACE_Message_Block *> (arg);
+ if (queue_.enqueue_tail (message) < 0)
+ {
+ if (is_active_)
+ ACE_ERROR ((LM_ERROR, "%t %p\n",
+ "Bounded_Packet_Relay::receive_input failed"));
+
+ return -1;
+ }
+
+ return 0;
+}
+
+// Get high water mark for relay queue.
+
+ACE_UINT32
+Bounded_Packet_Relay::queue_hwm (void)
+{
+ return queue_lwm_;
+}
+
+
+// Set high water mark for relay queue.
+
+void
+Bounded_Packet_Relay::queue_hwm (ACE_UINT32 hwm)
+{
+ queue_hwm_ = hwm;
+}
+
+// Get low water mark for relay queue.
+
+ACE_UINT32
+Bounded_Packet_Relay::queue_lwm (void)
+{
+ return queue_lwm_;
+}
+
+// Set low water mark for relay queue.
+
+void
+Bounded_Packet_Relay::queue_lwm (ACE_UINT32 lwm)
+{
+ queue_lwm_ = lwm;
+}
+
+
+
+// Returns string corresponding to current status.
+
+const char *
+Bounded_Packet_Relay::status_msg (void)
+{
+ const char *status_msg;
+ switch (status_)
+ {
+ case UN_INITIALIZED:
+ status_msg = "uninitialized";
+ break;
+ case STARTED:
+ status_msg = "in progress";
+ break;
+ case COMPLETED:
+ status_msg = "completed with all packets sent";
+ break;
+ case TIMED_OUT:
+ status_msg = "terminated by transmission duration timer";
+ break;
+ case CANCELLED:
+ status_msg = "cancelled by external control";
+ break;
+ case ERROR_DETECTED:
+ status_msg = "error was detected";
+ break;
+ default:
+ status_msg = "unknown transmission status";
+ break;
+ }
+
+ return status_msg;
+}
diff --git a/ACE/examples/Bounded_Packet_Relay/BPR_Drivers.h b/ACE/examples/Bounded_Packet_Relay/BPR_Drivers.h
new file mode 100644
index 00000000000..f39a544c512
--- /dev/null
+++ b/ACE/examples/Bounded_Packet_Relay/BPR_Drivers.h
@@ -0,0 +1,290 @@
+/* -*- C++ -*- */
+// $Id$
+
+// ============================================================================
+//
+// = LIBRARY
+// examples
+//
+// = FILENAME
+// BPR_Drivers.h
+//
+// = DESCRIPTION
+// This code builds abstractions to factor out common code from
+// the different possible implementations of the Timer_Queue based
+// bounded packet relay example.
+//
+// = AUTHORS
+// Chris Gill <cdgill@cs.wustl.edu> and
+// Douglas C. Schmidt <schmidt@cs.wustl.edu>
+//
+// Based on the Timer Queue Test example written by
+//
+// Carlos O'Ryan <coryan@cs.wustl.edu> and
+// Douglas C. Schmidt <schmidt@cs.wustl.edu> and
+// Sergio Flores-Gaitan <sergio@cs.wustl.edu>
+//
+// ============================================================================
+
+#ifndef _BPR_DRIVERS_H_
+#define _BPR_DRIVERS_H_
+
+#include "ace/Functor.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/Reactor.h"
+#include "ace/Task.h"
+
+// forward declarations
+class Input_Device_Wrapper_Base;
+class Output_Device_Wrapper_Base;
+
+class Bounded_Packet_Relay
+{
+ // = TITLE
+ // This class defines a packet relay abstraction for a
+ // transmission bounded external commands to start and end the
+ // transmission. The transmission may be bounded by the number
+ // of packets to send, the dration of the transmission, or any
+ // other factors.
+ //
+ // = DESCRIPTION
+ // The relay abstraction implemented by this class registers a
+ // callback command with an input device wrapper, and relays
+ // input to an output device at a pace specified in the start
+ // transmission call.
+public:
+ // = Enumerates possible status values for a transmission.
+ enum Transmission_Status
+ {
+ UN_INITIALIZED,
+ STARTED,
+ COMPLETED,
+ TIMED_OUT,
+ CANCELLED,
+ ERROR_DETECTED
+ };
+
+ enum Queue_Defaults
+ {
+ DEFAULT_HWM = 0x7FFFFFFF,
+ DEFAULT_LWM = 0x7FFFFFFF
+ };
+
+ typedef int (Bounded_Packet_Relay::*ACTION) (void *);
+ // Command entry point type definition.
+
+ // = Initialization method
+
+ Bounded_Packet_Relay (ACE_Thread_Manager *input_task_mgr,
+ Input_Device_Wrapper_Base *input_wrapper,
+ Output_Device_Wrapper_Base *output_wrapper);
+ // Constructor.
+
+ virtual ~Bounded_Packet_Relay (void);
+ // Destructor.
+
+ int send_input (void);
+ // Requests output be sent to output device.
+
+ int start_transmission (u_long packet_count,
+ u_long arrival_period,
+ int logging_level);
+ // Requests a transmission be started.
+
+ int end_transmission (Transmission_Status status);
+ // Requests a transmission be ended.
+
+ int report_statistics (void);
+ // Requests a report of statistics from the last transmission.
+
+ // = Command accessible entry points.
+
+ int receive_input (void *);
+ // Public entry point to which to push input.
+
+ // = Accessors and mutators for relay settings
+
+ ACE_UINT32 queue_hwm (void);
+ // Get high water mark for relay queue.
+
+ void queue_hwm (ACE_UINT32 hwm);
+ // Set high water mark for relay queue.
+
+ ACE_UINT32 queue_lwm (void);
+ // Get low water mark for relay queue.
+
+ void queue_lwm (ACE_UINT32 lwm);
+ // Set low water mark for relay queue.
+
+private:
+ // = Concurrency Management.
+
+ int is_active_;
+ // flag for whether or not a transmission is active
+
+ ACE_Thread_Manager * input_task_mgr_;
+ // Thread manager for the input device task.
+
+ Input_Device_Wrapper_Base * input_wrapper_;
+ // Pointer to the input device wrapper.
+
+ Output_Device_Wrapper_Base * output_wrapper_;
+ // Pointer to the output device wrapper.
+
+ ACE_Message_Queue<ACE_SYNCH> queue_;
+ // Queue used to buffer input messages.
+
+ ACE_UINT32 queue_hwm_;
+ // High water mark for relay queue.
+
+ ACE_UINT32 queue_lwm_;
+ // Low water mark for relay queue.
+
+ ACE_SYNCH_MUTEX transmission_lock_;
+ // Lock for thread-safe synchronization of transmission startup and
+ // termination.
+
+ // = Transmission Statistics
+
+ const char *status_msg (void);
+ // Returns string corresponding to current status.
+
+ u_long transmission_number_;
+ // Number of transmissions sent.
+
+ u_long packets_sent_;
+ // Count of packets sent in the most recent transmission.
+
+ Transmission_Status status_;
+ // Status of the current or most recent transmission.
+
+ ACE_Time_Value transmission_start_;
+ // Start time of the most recent transmission.
+
+ ACE_Time_Value transmission_end_;
+ // Ending time of the most recent transmission.
+
+};
+
+class Input_Device_Wrapper_Base : public ACE_Task_Base
+{
+ // = TITLE
+ // This class defines an abstract base class for an input device
+ // wrapper that hides the details of the specific device and
+ // provides a consistent message passing interface without
+ // knowing anything about the implementation of the input device
+ // or the message receiver.
+ //
+ // The abstract base class ctor takes a command template object
+ // that is instantiated with the correct receiver and action
+ // types. This command object is used to send newly created input
+ // messages to the receiver.
+ //
+ // The abstract base class is designed to operate in an active
+ // "push" mode, sending input data to the receiver whenever the
+ // data is ready. The underlying device may be active, notifying
+ // the wrapper when data is ready, or may be passive in which
+ // case the wrapper must rely on a reactive and/or polling
+ // mechanism.
+ //
+ // = DESCRIPTION
+ // Derived classes are responsible for filling in concrete
+ // definitions for the abstract message creation method and the
+ // svc method.
+public:
+ // = Initialization and termination methods.
+ Input_Device_Wrapper_Base (ACE_Thread_Manager *input_task_mgr);
+ // Constructor.
+
+ virtual ~Input_Device_Wrapper_Base ();
+ // Destructor.
+
+ int set_send_input_msg_cmd (ACE_Command_Base *send_input_msg_cmd);
+ // Sets send input message command in the input device driver
+ // object.
+
+ int set_input_period (u_long input_period);
+ // Sets period (in usecs) between when inputs are created.
+
+ int set_send_count (long count);
+ // Sets count of messages to send.
+
+ int request_stop (void);
+ // Requests that the input device stop sending messages and
+ // terminate its thread. Should return 1 if it will do so, 0 if it
+ // has already done so, or -1 if there is a problem doing so.
+
+ virtual int svc (void);
+ // This method runs the input device loop in the new thread.
+
+ virtual int modify_device_settings (void *) = 0;
+ // Provides an abstract interface to allow modifying device
+ // settings.
+
+protected:
+ virtual ACE_Message_Block *create_input_message (void) = 0;
+ // Creates a new message block, carrying data read from the
+ // underlying input device.
+
+ virtual int send_input_message (ACE_Message_Block *);
+ // Sends a newly created message block, carrying data read from the
+ // underlying input device, by passing a pointer to the message
+ // block to its command execution.
+
+ ACE_Command_Base *send_input_msg_cmd_;
+ // Send newly created input message.
+
+ u_long input_period_;
+ // Period between when input values are produced (usecs).
+
+ ACE_Reactor reactor_;
+ // Reactor used to multiplex input streams, timeouts.
+
+ int is_active_;
+ // Flag to indicate whether or not input object is
+ // (and should remain) active.
+
+ long send_count_;
+ // Count of messages to send before stopping (-1 indicates the
+ // device should not stop).
+
+ long current_count_;
+ // Currently remaining count of messages to send before stopping
+ // (-1 indicates the device should not stop).
+
+};
+
+class Output_Device_Wrapper_Base
+{
+ // = TITLE
+ // This class defines an abstract base class for an output device
+ // wrapper that hides the details of the specific device and
+ // provides a consistent write method interface without knowing
+ // anything about the implementation.
+ //
+ // = DESCRIPTION
+ // The abstract methods write_output_message () and
+ // modify_device_settings () are defined in derived classes to
+ // write the contents of the passed message out the underlying
+ // output device, and update device settings, respectively.
+public:
+
+ virtual ~Output_Device_Wrapper_Base (void);
+
+ virtual int write_output_message (void *) = 0;
+ // Writes contents of the passed message block out to the underlying
+ // output device.
+
+ virtual int modify_device_settings (void *) = 0;
+ // Provides an abstract interface to allow modifying device
+ // settings.
+};
+
+// include the templates
+#include "BPR_Drivers_T.h"
+
+#endif /* _BPR_DRIVERS_H_ */
diff --git a/ACE/examples/Bounded_Packet_Relay/BPR_Drivers_T.cpp b/ACE/examples/Bounded_Packet_Relay/BPR_Drivers_T.cpp
new file mode 100644
index 00000000000..6e597dfb9e5
--- /dev/null
+++ b/ACE/examples/Bounded_Packet_Relay/BPR_Drivers_T.cpp
@@ -0,0 +1,322 @@
+// $Id$
+
+// ============================================================================
+// = LIBRARY
+// examples
+//
+// = FILENAME
+// BPR_Driver.cpp
+//
+// = DESCRIPTION
+// This code builds an abstraction to factor out common code for
+// the different implementations of the Timer_Queue.
+//
+// = AUTHORS
+// Chris Gill <cdgill@cs.wustl.edu> and
+// Douglas C. Schmidt <schmidt@cs.wustl.edu>
+//
+// Based on the Timer Queue Test example written by
+//
+// Carlos O'Ryan <coryan@cs.wustl.edu> and
+// Douglas C. Schmidt <schmidt@cs.wustl.edu> and
+// Sergio Flores-Gaitan <sergio@cs.wustl.edu>
+//
+// ============================================================================
+
+#ifndef _BPR_DRIVER_T_CPP_
+#define _BPR_DRIVER_T_CPP_
+
+// #include BPR_Drivers.h instead of BPR_Drivers_T.h
+// to avoid problems with circular includes
+#include "BPR_Drivers.h"
+#include "ace/OS_NS_string.h"
+#include "ace/OS_NS_unistd.h"
+
+ACE_RCSID(Bounded_Packet_Relay, BPR_Drivers_T, "$Id$")
+
+// Constructor.
+
+template <class TQ>
+Bounded_Packet_Relay_Driver<TQ>::Bounded_Packet_Relay_Driver (void)
+ : packet_count_cmd_ (0),
+ arrival_period_cmd_ (0),
+ transmit_period_cmd_ (0),
+ duration_limit_cmd_ (0),
+ logging_level_cmd_ (0),
+ run_transmission_cmd_ (0),
+ cancel_transmission_cmd_ (0),
+ report_stats_cmd_ (0),
+ shutdown_cmd_ (0),
+ packet_count_ (1000),
+ arrival_period_ (10000),
+ send_period_ (10000),
+ duration_limit_ (20000000),
+ logging_level_ (0)
+{
+}
+
+// Destructor.
+
+template <class TQ>
+Bounded_Packet_Relay_Driver<TQ>::~Bounded_Packet_Relay_Driver (void)
+{
+ // delete all instantiated command objects
+ delete packet_count_cmd_;
+ delete arrival_period_cmd_;
+ delete transmit_period_cmd_;
+ delete duration_limit_cmd_;
+ delete logging_level_cmd_;
+ delete run_transmission_cmd_;
+ delete cancel_transmission_cmd_;
+ delete report_stats_cmd_;
+ delete shutdown_cmd_;
+}
+
+// Parse the input and execute the corresponding command.
+
+template <class TQ> int
+Bounded_Packet_Relay_Driver<TQ>::parse_commands (const char *buf)
+{
+ int option;
+
+ if (::sscanf (buf, "%d", &option) <= 0)
+ // If there was an error reading the option simply try on the next
+ // line.
+ return 0;
+
+ switch (option)
+ {
+ case 1: // set packet count
+ {
+ u_long count;
+
+ // We just reread the option, this simplies parsing (since
+ // sscanf can do it for us).
+ if (::sscanf (buf, "%d %lu", &option, &count) < 2)
+ // If there was not enough information on the line, ignore
+ // option and try the next line.
+ return 0;
+ if (packet_count_cmd_->execute ((void *) &count) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%t %p\n",
+ "set packet count failed"),
+ -1);
+ break;
+ }
+ case 2: // Set the arrival period.
+ {
+ u_long usec;
+
+ // We just reread the option, this simplies parsing (since
+ // sscanf can do it for us).
+ if (::sscanf (buf, "%d %lu", &option, &usec) < 2)
+ // If there was not enough information on the line, ignore
+ // option and try the next line.
+ return 0;
+ if (arrival_period_cmd_->execute ((void *) &usec) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%t %p\n",
+ "set arrival period failed"),
+ -1);
+ break;
+ }
+ case 3: // Set transmit period.
+ {
+ u_long usec;
+
+ // We just reread the option, this simplies parsing (since
+ // sscanf can do it for us).
+ if (::sscanf (buf, "%d %lu", &option, &usec) < 2)
+ // If there was not enough information on the line, ignore
+ // option and try the next line.
+ return 0;
+ if (transmit_period_cmd_->execute ((void *) &usec) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%t %p\n",
+ "set transmit period failed"),
+ -1);
+ break;
+ }
+ case 4: // Set duration limit.
+ {
+ u_long usec;
+
+ // We just reread the option, this simplies parsing (since
+ // sscanf can do it for us).
+ if (::sscanf (buf, "%d %lu", &option, &usec) < 2)
+ // If there was not enough information on the line, ignore
+ // option and try the next line.
+ return 0;
+ if (duration_limit_cmd_->execute ((void *) &usec) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%t %p\n",
+ "\nSet duration limit failed."),
+ -1);
+ break;
+ }
+ case 5: // Set logging level.
+ {
+ int level;
+
+ // We just reread the option, this simplies parsing (since
+ // sscanf can do it for us).
+ if ((::sscanf (buf, "%d %d", &option, &level) < 2) ||
+ (level < 0) || (level > 7))
+ {
+ // If there was not enough information on the line, or the
+ // passed value was invalid, ignore and try again.
+ return 0;
+ }
+
+ if (logging_level_cmd_->execute ((void *) &level) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%t %p\n",
+ "set logging level failed"),
+ -1);
+ break;
+ }
+ case 6: // Run one transmission.
+ return run_transmission_cmd_->execute (0);
+ /* NOTREACHED */
+ case 7: // Cancel current transmission.
+ return cancel_transmission_cmd_->execute (0);
+ /* NOTREACHED */
+ case 8: // Report statistics.
+ return report_stats_cmd_->execute (0);
+ /* NOTREACHED */
+ case 9: // Shut down the driver.
+ return shutdown_cmd_->execute (0);
+ /* NOTREACHED */
+ default:
+ // Display an error message.
+ ACE_ERROR_RETURN ((LM_ERROR, "invalid input %s\n", buf), 0);
+ ACE_NOTREACHED (break);
+ /* NOTREACHED */
+ } /* ENDSWITCH */
+ return 0;
+}
+
+// Runs the test.
+
+template <class TQ> int
+Bounded_Packet_Relay_Driver<TQ>::run (void)
+{
+ this->init ();
+
+ // Process all the incoming events.
+
+ for (;;)
+ if (this->get_next_request () == -1)
+ return -1;
+
+ ACE_NOTREACHED (return 0);
+}
+
+// Gets the next request from the user input.
+
+template <class TQ> int
+Bounded_Packet_Relay_Driver<TQ>::get_next_request (void)
+{
+ char buf[BUFSIZ];
+
+ this->display_menu ();
+
+ // Reads input from the user.
+ if (this->read_input (buf, sizeof buf) <= 0)
+ return -1;
+
+ // Parse and run the command.
+ return this->parse_commands (buf);
+}
+
+// Reads input from the user from ACE_STDIN into the buffer specified.
+
+template <class TQ> ssize_t
+Bounded_Packet_Relay_Driver<TQ>::read_input (char *buf, size_t bufsiz)
+{
+ ACE_OS::memset (buf, 0, bufsiz);
+
+ // Wait for user to type commands. This call is automatically
+ // restarted when SIGINT or SIGALRM signals occur.
+ return ACE_OS::read (ACE_STDIN, buf, bufsiz);
+}
+
+// Get count of packets to send in a transmission.
+
+template <class TQ> u_long
+Bounded_Packet_Relay_Driver<TQ>::packet_count (void)
+{
+ return packet_count_;
+}
+
+// Set count of packets to send in a transmission.
+
+template <class TQ> void
+Bounded_Packet_Relay_Driver<TQ>::packet_count (u_long pc)
+{
+ packet_count_ = pc;
+}
+
+// Get rate at which input packets are to arrive.
+
+template <class TQ> u_long
+Bounded_Packet_Relay_Driver<TQ>::arrival_period (void)
+{
+ return arrival_period_;
+}
+
+// Set rate at which input packets are to arrive.
+
+template <class TQ> void
+Bounded_Packet_Relay_Driver<TQ>::arrival_period (u_long ap)
+{
+ arrival_period_ = ap;
+}
+
+// Get rate at which packets are to be relayed (usec).
+
+template <class TQ> u_long
+Bounded_Packet_Relay_Driver<TQ>::send_period (void)
+{
+ return send_period_;
+}
+
+// Set rate at which packets are to be relayed (usec).
+
+template <class TQ> void
+Bounded_Packet_Relay_Driver<TQ>::send_period (u_long sp)
+{
+ send_period_ = sp;
+}
+
+// Get limit on the duration of the transmission (usec).
+
+template <class TQ> u_long
+Bounded_Packet_Relay_Driver<TQ>::duration_limit (void)
+{
+ return duration_limit_;
+}
+
+// Set limit on the duration of the transmission (usec).
+
+template <class TQ> void
+Bounded_Packet_Relay_Driver<TQ>::duration_limit (u_long dl)
+{
+ duration_limit_ = dl;
+}
+// Get logging level.
+
+template <class TQ> int
+Bounded_Packet_Relay_Driver<TQ>::logging_level (void)
+{
+ return logging_level_;
+}
+
+// Set logging level.
+
+template <class TQ> void
+Bounded_Packet_Relay_Driver<TQ>::logging_level (int ll)
+{
+ logging_level_ = ll;
+}
+#endif /* _BPR_DRIVER_T_CPP_ */
diff --git a/ACE/examples/Bounded_Packet_Relay/BPR_Drivers_T.h b/ACE/examples/Bounded_Packet_Relay/BPR_Drivers_T.h
new file mode 100644
index 00000000000..4d0ca6bdfb4
--- /dev/null
+++ b/ACE/examples/Bounded_Packet_Relay/BPR_Drivers_T.h
@@ -0,0 +1,178 @@
+/* -*- C++ -*- */
+// $Id$
+
+// ============================================================================
+//
+// = LIBRARY
+// examples
+//
+// = FILENAME
+// BPR_Drivers_T.h
+//
+// = DESCRIPTION
+// This code factors out common class templates for use in
+// the different possible implementations of the Timer_Queue
+// based bounded packet relay example.
+//
+// = AUTHORS
+// Chris Gill <cdgill@cs.wustl.edu> and
+// Douglas C. Schmidt <schmidt@cs.wustl.edu>
+//
+// Based on the Timer Queue Test example written by
+//
+// Carlos O'Ryan <coryan@cs.wustl.edu> and
+// Douglas C. Schmidt <schmidt@cs.wustl.edu> and
+// Sergio Flores-Gaitan <sergio@cs.wustl.edu>
+//
+// ============================================================================
+
+#ifndef _BPR_DRIVERS_T_H_
+#define _BPR_DRIVERS_T_H_
+
+#include "ace/Functor.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+// Forward declarations.
+class Input_Device_Wrapper_Base;
+class Output_Device_Wrapper_Base;
+
+template <class TQ>
+class Bounded_Packet_Relay_Driver
+{
+ // = TITLE
+ // This abstract base class provides a simple abstraction for a
+ // test driver for the bounded packet relay example.
+ //
+ // = DESCRIPTION
+ // This is the place where the common code to test the different
+ // implementations of the timer queue resides. This class has
+ // the logic for the parse_commands () method, the run (),
+ // read_input () and get_next_request () methods. Subclasses can
+ // override these methods if there is some logic that is specific
+ // to that implementation.
+public:
+ Bounded_Packet_Relay_Driver (void);
+ // Constructor.
+
+ virtual ~Bounded_Packet_Relay_Driver (void);
+ // Destructor.
+
+ virtual int parse_commands (const char *buf);
+ // Breaks up the input string buffer into pieces and executes the
+ // appropriate method to handle that operation.
+
+ virtual int run (void);
+ // This is the main entry point for the driver. The user of the
+ // class should normally invoke this method. Returns 0 when
+ // successful, or 0 otherwise.
+
+ virtual int get_next_request (void);
+ // This internal method gets the next request from the user.
+ // Returns -1 when user wants to exit. Returns 0 otherwise.
+
+ virtual ssize_t read_input (char *buf, size_t bufsiz);
+ // Reads input from the user into the buffer <buf> with a maximum of
+ // <bufsiz> bytes. Returns the amount of bytes actually read
+ // Otherwise, a -1 is returned and errno is set to indicate the
+ // error.
+
+ virtual int display_menu (void)=0;
+ // Prints the user interface for the driver to STDERR.
+
+ virtual int init (void)=0;
+ // Initializes values and operations for the driver.
+
+ u_long packet_count (void);
+ // Get count of packets to send in a transmission.
+
+ void packet_count (u_long pc);
+ // Set count of packets to send in a transmission.
+
+ u_long arrival_period (void);
+ // Get rate at which input packets are to arrive.
+
+ void arrival_period (u_long ap);
+ // Set rate at which input packets are to arrive.
+
+ u_long send_period (void);
+ // Get rate at which packets are to be relayed (usec).
+
+ void send_period (u_long sp);
+ // Set rate at which packets are to be relayed (usec).
+
+ u_long duration_limit (void);
+ // Get limit on the duration of the transmission (usec).
+
+ void duration_limit (u_long dl);
+ // Set limit on the duration of the transmission (usec).
+
+ int logging_level (void);
+ // Get logging level.
+
+ void logging_level (int ll);
+ // Set logging level.
+
+protected:
+ // = Major Driver Mechanisms
+
+ TQ timer_queue_;
+ // Timer queue for transmission timeouts.
+
+ // = Set of commands to be executed.
+
+ ACE_Command_Base *packet_count_cmd_;
+ // Set packet count command.
+
+ ACE_Command_Base *arrival_period_cmd_;
+ // Set arrival period command.
+
+ ACE_Command_Base *transmit_period_cmd_;
+ // Set transmit period command.
+
+ ACE_Command_Base *duration_limit_cmd_;
+ // Set duration limit command.
+
+ ACE_Command_Base *logging_level_cmd_;
+ // Set logging level command.
+
+ ACE_Command_Base *run_transmission_cmd_;
+ // Run transmission command.
+
+ ACE_Command_Base *cancel_transmission_cmd_;
+ // Cancel transmission command.
+
+ ACE_Command_Base *report_stats_cmd_;
+ // Report statistics command.
+
+ ACE_Command_Base *shutdown_cmd_;
+ // Shut down the driver.
+
+private:
+ u_long packet_count_;
+ // Count of packets to send in a transmission.
+
+ u_long arrival_period_;
+ // Rate at which input packets are to arrive.
+
+ u_long send_period_;
+ // Rate at which packets are to be relayed (usec).
+
+ u_long duration_limit_;
+ // Limit on the duration of the transmission (usec).
+
+ int logging_level_;
+ // Logging level.
+};
+
+#if defined (ACE_TEMPLATES_REQUIRE_SOURCE)
+#include "BPR_Drivers_T.cpp"
+#endif /* ACE_TEMPLATES_REQUIRE_SOURCE */
+
+#if defined (ACE_TEMPLATES_REQUIRE_PRAGMA)
+#pragma implementation ("BPR_Drivers_T.cpp")
+#endif /* ACE_TEMPLATES_REQUIRE_PRAGMA */
+
+#endif /* _BPR_DRIVERS_T_H_ */
diff --git a/ACE/examples/Bounded_Packet_Relay/Bounded_Packet_Relay.mpc b/ACE/examples/Bounded_Packet_Relay/Bounded_Packet_Relay.mpc
new file mode 100644
index 00000000000..087cc5ac3be
--- /dev/null
+++ b/ACE/examples/Bounded_Packet_Relay/Bounded_Packet_Relay.mpc
@@ -0,0 +1,7 @@
+// -*- MPC -*-
+// $Id$
+
+project : aceexe {
+ exename = bpr_thread
+ macros += ACE_HAS_DEFERRED_TIMER_COMMANDS
+}
diff --git a/ACE/examples/Bounded_Packet_Relay/Makefile.am b/ACE/examples/Bounded_Packet_Relay/Makefile.am
new file mode 100644
index 00000000000..5fb14ba2d05
--- /dev/null
+++ b/ACE/examples/Bounded_Packet_Relay/Makefile.am
@@ -0,0 +1,39 @@
+## Process this file with automake to create Makefile.in
+##
+## $Id$
+##
+## This file was generated by MPC. Any changes made directly to
+## this file will be lost the next time it is generated.
+##
+## MPC Command:
+## /acebuilds/ACE_wrappers-repository/bin/mwc.pl -include /acebuilds/MPC/config -include /acebuilds/MPC/templates -feature_file /acebuilds/ACE_wrappers-repository/local.features -noreldefs -type automake -exclude build,Kokyu
+
+ACE_BUILDDIR = $(top_builddir)
+ACE_ROOT = $(top_srcdir)
+
+## Makefile.Bounded_Packet_Relay.am
+noinst_PROGRAMS = bpr_thread
+
+bpr_thread_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR) \
+ -DACE_HAS_DEFERRED_TIMER_COMMANDS
+
+bpr_thread_SOURCES = \
+ BPR_Drivers.cpp \
+ Thread_Bounded_Packet_Relay.cpp \
+ bpr_thread.cpp \
+ BPR_Drivers.h \
+ BPR_Drivers_T.h \
+ Thread_Bounded_Packet_Relay.h
+
+bpr_thread_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Clean up template repositories, etc.
+clean-local:
+ -rm -f *~ *.bak *.rpo *.sym lib*.*_pure_* core core.*
+ -rm -f gcctemp.c gcctemp so_locations *.ics
+ -rm -rf cxx_repository ptrepository ti_files
+ -rm -rf templateregistry ir.out
+ -rm -rf ptrepository SunWS_cache Templates.DB
diff --git a/ACE/examples/Bounded_Packet_Relay/README b/ACE/examples/Bounded_Packet_Relay/README
new file mode 100644
index 00000000000..5757224c510
--- /dev/null
+++ b/ACE/examples/Bounded_Packet_Relay/README
@@ -0,0 +1,194 @@
+1. INTRODUCTION
+
+This directory contains an example that illustrates how to use both
+threaded and reactive concurrency mechanisms in ACE. The example
+application schedules and processes heterogenerous user input and
+timer-based events in the context of a bounded packet relay mechanism.
+
+In this example, a transmission begins, packets arrive from an input device
+object, and are transferred to an output device object by a relay object at
+a specified pace. The transfer continues until all packets have been
+relayed, a duration limit expires, or the transmission is cancelled.
+
+User input is handled concurrently with a running transmission. You
+can run a transmission, cancel a transmission, change transmission
+parameters, view statistics from the most recent transmission, or exit
+the program, using selections from an interactive text-based menu.
+In addition, the example program can be run in batch mode, with the
+appropriate commands piped to the program's standard input stream.
+
+Transmission parameters are intialized to default values. Transmission
+parameter values persist until/unless they are subsequently modified by an
+appropriate command. If an invalid value for a command is given, or a run
+or report command is issued while a transmission is in progress, the
+offending command has no effect, and an error message is generated.
+
+2. USER INTERFACE
+
+Commands that can be given to the program include the following:
+
+Settings commands:
+
+ 1 <number of packets to relay in one transmission>
+
+ Minimum value is 1 packet, defaults to 1000 packets.
+
+ 2 <input packet arrival period (in usec)>
+
+ Minimum value is 1 usec, defaults to 10000 usec (10 msec).
+
+ 3 <output packet transmission period (in usec)>
+
+ Minimum value is 1 usec, defaults to 10000 usec (10 msec).
+
+ 4 <limit on duration of transmission (in usec)>
+
+ Minimum value is 1 usec, defaults to 20000000 usec (20 sec).
+ A value of 0 is also a valid input, in which case no limit
+ will be placed on the duration of the transmission (it will
+ end when all packets have been relayed from the input device
+ to the output device).
+
+ 5 <logging level>
+
+ 0 - does no logging
+ 1 - logs packets created by the input device
+ 2 - logs packets consumed by the output device
+ 4 - prints contents of packets consumed by the output device
+
+ To set several flags, pass their sum as the logging level value:
+ e.g., a logging level value of 7 turns on all possible logging.
+
+Action commands:
+
+ 6 - runs a transmission using the current settings
+
+ 7 - cancels a transmission if there is one running
+
+ 8 - reports statistics from the most recent transmission
+
+ 9 - quits the program
+
+3. APPLICATION DESIGN
+
+3.1. KEY COMPONENTS
+
+The design of this example application consists of four main
+components: the driver object, the relay object, the input device
+object, and the output device object.
+
+The driver object is responsible for receiving user input and overall handling
+of user input commands. The driver object is active, with separate threads
+for receiving user input and managing its transmission timer queue. This
+allows the user to issue commands while a transmission is in progress. The
+driver object uses an ACE_Thread_Timer_Queue_Adapter, which is derived from
+ACE_Task_Base. The driver object starts another active object, called
+User_Input_Task, which is also derived from ACE_Task_Base. This allows both
+the timer queue and the user input object to be made active, running in their
+own threads of control.
+
+The relay object is passive, managing a message queue and necessary
+locks to allow safe access from multiple threads. It provides methods
+to receive and enqueue a mesage from the input device, dequeue a
+message and send it to the output device, and to start or end a
+transmission. It uses ACE_Message_Queue (which contains ACE_Message_Block
+objects) and ACE_Thread_Mutex objects to implement this functionality.
+
+The input object is active, managing timeouts and input events in its
+own thread. The input object is also reactive, using an ACE_Reactor to
+allow response to multiple input handles as well as to do polling at
+specific timeouts. The input pseudo-device wrapper in this example
+does not make use of input handles and only does timed polling, but
+extending this only requires registering the appropriate input handles
+and handlers with the reactor. The input object is derived from
+ACE_Task_Base, and is activated by the relay object when a new
+transmission starts. The input object packages each data packet in an
+ACE_Message_Block before sending it to the relay object.
+
+The output object is passive. If logging is turned on, it will report
+the arrival time, relative to the start of the transmission, of each
+output message, and the contents of that message. The output object
+will also "consume" each ACE_Message_Block passed to it, calling
+delete on the passed pointer.
+
+3.2. RUN-TIME CHARACTERSITICS
+
+When the user initiates a transmission, the appropriate settings are passed
+by the driver to the relay object's start transmission method. The relay
+object tries to start a new transmission. If another transmission is in
+progress, the method returns an error. Otherwise, the relay object's start
+transmission method initializes itself and the input and output device
+objects, activates the input device object, and stores the handle for
+the new input device thread.
+
+The driver then constructs a timeout handler with a count of the
+number of messages to relay and a send timeout value, and pushes a
+timer with this handler onto the timer queue. If there is a limit on
+the duration of the transmission, the driver constructs a different
+handler for end-of-transmission, and pushes a timer for the end of
+the transmission with this handler onto the timer queue as well. When
+the user issues a cancel transmission command, the driver calls the
+relay's end transmission method.
+
+When a send timeout expires, the handler (running in the timer queue
+thread) calls the send method of the relay. If there are any enqueued
+messages from the input device object in its queue, the relay object's
+send method will dequeue a message, pass it to the output device
+object, and return success. If there are no messages in the queue,
+the relay object's send method will return failure. If the send was
+successful, the handler will decrement its count of remaining
+messages. If the count is greater than zero, the handler will
+register a new send timer for itself and exit. If the count is zero,
+then the handler will call the relay's end transmission method, clear
+the timer queue, and mark itself inactive before exiting.
+
+Similarly, if the end-of-transmission timer expires before all packets
+have been sent, that handler will call the relay's end transmission
+method, clear the timer queue, release the semaphore, and then exit.
+
+When the relay's end transmission method is called, it marks the relay
+itself inactive, and calls the input device's deactivate method, which
+sets the input device's activity flag to inactive (see below). The
+relay's end transmission method then waits until the input device thread
+exits, before returning.
+
+While it is still active, the input device thread blocks on a reactor
+timeout for the duration it was given by the relay. When the timeout
+expires, the input device checks a flag to see if it is still active.
+If the flag says the input device is inactive, the thread simply
+exits. This allows cancellation of the input device when a
+transmission has ended. If the flag says it is still active, the
+thread builds a new character buffer, and wraps this with a new
+ACE_Message_Block. The input device passes this message block to the
+execution method of the send input message command object with which
+it was constructed. This level of indirection allows the input device
+to be used with arbitrary types, so that it could for example be
+connected directly to an output device. The input device also
+maintains a count of the number of messages it has sent. Once the
+input device has sent all its messages, it marks itself inactive, and
+its thread simply exits.
+
+4. ACCESSING THE SOURCE CODE
+
+The files for this example are located in
+$ACE_ROOT/examples/Bounded_Packet_Relay in the latest release of ACE,
+which is located at
+
+http://www.cs.wustl.edu/~schmidt/ACE_wrappers/ACE.tar.gz
+
+Source Files: Thread_Bounded_Packet_Relay.h
+ Thread_Bounded_Packet_Relay.cpp
+ BPR_Driver.h
+ BPR_Driver.cpp
+ BPR_Driver_T.h
+ BPR_Driver_T.cpp
+ bpr_thread.cpp
+
+Make file: Makefile
+
+Doc file: README (this file)
+
+Executable: bpr_thread
+
+
+
diff --git a/ACE/examples/Bounded_Packet_Relay/Thread_Bounded_Packet_Relay.cpp b/ACE/examples/Bounded_Packet_Relay/Thread_Bounded_Packet_Relay.cpp
new file mode 100644
index 00000000000..a2f179a5348
--- /dev/null
+++ b/ACE/examples/Bounded_Packet_Relay/Thread_Bounded_Packet_Relay.cpp
@@ -0,0 +1,770 @@
+// $Id$
+
+// ============================================================================
+//
+// = LIBRARY
+// examples
+//
+// = FILENAME
+// Thread_Bounded_Packet_Relay.cpp
+//
+// = DESCRIPTION
+// Method definitions for the threaded-bounded packet relay class.
+//
+// = AUTHORS
+// Chris Gill <cdgill@cs.wustl.edu> and
+// Douglas C. Schmidt <schmidt@cs.wustl.edu>
+//
+// Based on the Timer Queue Test example written by
+//
+// Carlos O'Ryan <coryan@cs.wustl.edu> and
+// Douglas C. Schmidt <schmidt@cs.wustl.edu> and
+// Sergio Flores-Gaitan <sergio@cs.wustl.edu>
+//
+// ============================================================================
+
+#include "ace/OS_NS_string.h"
+#include "ace/OS_NS_sys_time.h"
+#include "ace/Condition_T.h"
+#include "ace/Null_Mutex.h"
+
+#include "Thread_Bounded_Packet_Relay.h"
+
+typedef Thread_Bounded_Packet_Relay_Driver::MYCOMMAND DRIVER_CMD;
+typedef ACE_Command_Callback<BPR_Handler_Base, BPR_Handler_Base::ACTION> HANDLER_CMD;
+typedef ACE_Command_Callback<Send_Handler, Send_Handler::ACTION> SEND_HANDLER_CMD;
+
+ACE_RCSID(Bounded_Packet_Relay, Thread_Bounded_Packet_Relay, "$Id$")
+
+// Constructor.
+
+Text_Input_Device_Wrapper::Text_Input_Device_Wrapper (ACE_Thread_Manager *input_task_mgr,
+ size_t read_length,
+ const char* text,
+ int logging)
+ : Input_Device_Wrapper_Base (input_task_mgr),
+ read_length_ (read_length),
+ text_ (text),
+ index_ (0),
+ logging_ (logging),
+ packet_count_ (0)
+
+{
+}
+
+// Destructor.
+
+Text_Input_Device_Wrapper::~Text_Input_Device_Wrapper (void)
+{
+}
+
+// Modifies device settings based on passed pointer to a u_long.
+
+int
+Text_Input_Device_Wrapper::modify_device_settings (void *logging)
+{
+ packet_count_ = 0;
+
+ if (logging)
+ logging_ = *static_cast<int *> (logging);
+ else
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Text_Input_Device_Wrapper::modify_device_settings: "
+ "null argument"),
+ -1);
+ return 0;
+}
+
+
+// Creates a new message block, carrying data
+// read from the underlying input device.
+
+ACE_Message_Block *
+Text_Input_Device_Wrapper::create_input_message (void)
+{
+
+ // Construct a new message block to send.
+ ACE_Message_Block *mb;
+ ACE_NEW_RETURN (mb,
+ ACE_Message_Block (read_length_),
+ 0);
+
+ // Zero out a "read" buffer to hold data.
+ char read_buf [BUFSIZ];
+ ACE_OS::memset (read_buf, 0, BUFSIZ);
+
+ // Loop through the text, filling in data to copy into the read
+ // buffer (leaving room for a terminating zero).
+ for (size_t i = 0; i < read_length_ - 1; ++i)
+ {
+ read_buf [i] = text_ [index_];
+ index_ = (index_ + 1) % ACE_OS::strlen (text_);
+ }
+
+ // Copy buf into the Message_Block and update the wr_ptr ().
+ if (mb->copy (read_buf, read_length_) < 0)
+ {
+ delete mb;
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "read buffer copy failed"),
+ 0);
+ }
+
+ // log packet creation if logging is turned on
+ if (logging_ & Text_Input_Device_Wrapper::LOG_MSGS_CREATED)
+ {
+ ++packet_count_;
+ ACE_DEBUG ((LM_DEBUG, "input message %d created\n",
+ packet_count_));
+ }
+
+ return mb;
+}
+
+// Constructor.
+
+Text_Output_Device_Wrapper::Text_Output_Device_Wrapper (int logging)
+ : logging_ (logging)
+{
+}
+
+// Consume and possibly print out the passed message.
+
+int
+Text_Output_Device_Wrapper::write_output_message (void *message)
+{
+ if (message)
+ {
+ ++packet_count_;
+
+ if (logging_ & Text_Output_Device_Wrapper::LOG_MSGS_RCVD)
+ ACE_DEBUG ((LM_DEBUG, "output message %d received\n",
+ packet_count_));
+
+ if (logging_ & Text_Output_Device_Wrapper::PRINT_MSGS_RCVD)
+ ACE_DEBUG ((LM_DEBUG, "output message %d:\n[%s]\n",
+ packet_count_,
+ static_cast<ACE_Message_Block *> (message)->
+ rd_ptr ()));
+
+ delete static_cast<ACE_Message_Block *> (message);
+ return 0;
+ }
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Text_Output_Device_Wrapper::"
+ "write_output_message: null argument"), -1);
+}
+
+// Modifies device settings based on passed pointer to a u_long.
+
+int
+Text_Output_Device_Wrapper::modify_device_settings (void *logging)
+{
+ packet_count_ = 0;
+
+ if (logging)
+ logging_ = *static_cast<int *> (logging);
+ else
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Text_Output_Device_Wrapper::modify_device_settings: "
+ "null argument"),
+ -1);
+ return 0;
+}
+
+// Constructor.
+
+User_Input_Task::User_Input_Task (Bounded_Packet_Relay *relay,
+ Thread_Timer_Queue *queue,
+ Thread_Bounded_Packet_Relay_Driver &tbprd)
+ : ACE_Task_Base (ACE_Thread_Manager::instance ()),
+ usecs_ (ACE_ONE_SECOND_IN_USECS),
+ relay_ (relay),
+ queue_ (queue),
+ driver_ (tbprd)
+{
+}
+
+// Destructor.
+
+User_Input_Task::~User_Input_Task (void)
+{
+ this->clear_all_timers ();
+}
+
+// Runs the main event loop.
+
+int
+User_Input_Task::svc (void)
+{
+ for (;;)
+ // Call back to the driver's implementation of how to read and
+ // parse input.
+ if (this->driver_.get_next_request () == -1)
+ break;
+
+ // We are done.
+ this->relay_->end_transmission (Bounded_Packet_Relay::CANCELLED);
+ this->queue_->deactivate ();
+ ACE_DEBUG ((LM_DEBUG,
+ "terminating user input thread\n"));
+ this->clear_all_timers ();
+ return 0;
+}
+
+// Sets the number of packets for the next transmission.
+
+int
+User_Input_Task::set_packet_count (void *argument)
+{
+ if (argument)
+ {
+ driver_.packet_count (*static_cast<int *> (argument));
+ return 0;
+ }
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "User_Input_Task::set_packet_count: null argument"),
+ -1);
+}
+
+// Sets the input device packet arrival period (usecs) for the next
+// transmission.
+
+int
+User_Input_Task::set_arrival_period (void *argument)
+{
+ if (argument)
+ {
+ driver_.arrival_period (*static_cast<int *> (argument));
+ return 0;
+ }
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "User_Input_Task::set_arrival_period: null argument"),
+ -1);
+}
+
+// Sets the period between output device sends (usecs) for the next
+// transmission.
+
+int
+User_Input_Task::set_send_period (void *argument)
+{
+ if (argument)
+ {
+ driver_.send_period (*static_cast<int *> (argument));
+ return 0;
+ }
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "User_Input_Task::set_send_period: null argument"),
+ -1);
+}
+
+// Sets a limit on the transmission duration (usecs).
+
+int
+User_Input_Task::set_duration_limit (void *argument)
+{
+ if (argument)
+ {
+ driver_.duration_limit (*static_cast<int *> (argument));
+ return 0;
+ }
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "User_Input_Task::set_duration_limit: null argument"),
+ -1);
+}
+
+// Sets logging level (0 or 1) for output device for the next
+// transmission.
+
+int
+User_Input_Task::set_logging_level (void *argument)
+{
+ if (argument)
+ {
+ driver_.logging_level (*static_cast<int *> (argument));
+ return 0;
+ }
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "User_Input_Task::set_logging_level: null argument"),
+ -1);
+}
+
+// Runs the next transmission (if one is not in progress).
+
+int
+User_Input_Task::run_transmission (void *)
+{
+ if (relay_)
+ {
+ switch (relay_->start_transmission (driver_.packet_count (),
+ driver_.arrival_period (),
+ driver_.logging_level ()))
+ {
+ case 1:
+ ACE_DEBUG ((LM_DEBUG,
+ "\nRun transmission: "
+ " Transmission already in progress\n"));
+ return 0;
+ /* NOTREACHED */
+ case 0:
+ {
+ ACE_Time_Value now = ACE_OS::gettimeofday ();
+ ACE_Time_Value send_every (0, driver_.send_period ());
+ ACE_Time_Value send_at (send_every + now);
+
+ Send_Handler *send_handler;
+ ACE_NEW_RETURN (send_handler,
+ Send_Handler (driver_.packet_count (),
+ send_every,
+ *relay_,
+ *queue_,
+ driver_),
+ -1);
+ if (queue_->schedule (send_handler, 0, send_at) < 0)
+ {
+ delete send_handler;
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "User_Input_Task::run_transmission: "
+ "failed to schedule send handler"),
+ -1);
+ }
+ if (driver_.duration_limit ())
+ {
+ ACE_Time_Value terminate_at (0, driver_.duration_limit ());
+ terminate_at += now;
+
+ Termination_Handler *termination_handler;
+
+ termination_handler =
+ new Termination_Handler (*relay_,
+ *queue_,
+ driver_);
+
+ if (! termination_handler)
+ {
+ this->clear_all_timers ();
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "User_Input_Task::run_transmission: "
+ "failed to allocate termination "
+ "handler"),
+ -1);
+ }
+ if (queue_->schedule (termination_handler,
+ 0, terminate_at) < 0)
+ {
+ delete termination_handler;
+ this->clear_all_timers ();
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "User_Input_Task::run_transmission: "
+ "failed to schedule termination "
+ "handler"),
+ -1);
+ }
+ }
+ return 0;
+ }
+ /* NOTREACHED */
+ default:
+ return -1;
+ /* NOTREACHED */
+ }
+ }
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "User_Input_Task::run_transmission: "
+ "relay not instantiated"),
+ -1);
+}
+
+// Ends the current transmission (if one is in progress).
+
+int
+User_Input_Task::end_transmission (void *)
+{
+ if (relay_)
+ {
+ switch (relay_->end_transmission (Bounded_Packet_Relay::CANCELLED))
+ {
+ case 1:
+ ACE_DEBUG ((LM_DEBUG,
+ "\nEnd transmission: "
+ "no transmission in progress\n"));
+ /* Fall through to next case */
+ case 0:
+ // Cancel any remaining timers.
+ this->clear_all_timers ();
+ return 0;
+ /* NOTREACHED */
+ default:
+ return -1;
+ /* NOTREACHED */
+ }
+ }
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "User_Input_Task::end_transmission: "
+ "relay not instantiated"),
+ -1);
+}
+
+// Reports statistics for the previous transmission
+// (if one is not in progress).
+
+int
+User_Input_Task::report_stats (void *)
+{
+ if (relay_)
+ {
+ switch (relay_->report_statistics ())
+ {
+ case 1:
+ ACE_DEBUG ((LM_DEBUG,
+ "\nRun transmission: "
+ "\ntransmission already in progress\n"));
+ return 0;
+ /* NOTREACHED */
+
+ case 0:
+ this->clear_all_timers ();
+ return 0;
+ /* NOTREACHED */
+
+ default:
+ return -1;
+ /* NOTREACHED */
+ }
+ }
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "User_Input_Task::report_stats: "
+ "relay not instantiated"),
+ -1);
+}
+
+// Shut down the task.
+
+int
+User_Input_Task::shutdown (void *)
+{
+ // Clear any outstanding timers.
+ this->clear_all_timers ();
+
+#if !defined (ACE_LACKS_PTHREAD_CANCEL)
+ // Cancel the thread timer queue task "preemptively."
+ ACE_Thread::cancel (this->queue_->thr_id ());
+#else
+ // Cancel the thread timer queue task "voluntarily."
+ this->queue_->deactivate ();
+#endif /* ACE_LACKS_PTHREAD_CANCEL */
+
+ // -1 indicates we are shutting down the application.
+ return -1;
+}
+
+// Helper method: clears all timers.
+
+int
+User_Input_Task::clear_all_timers (void)
+{
+ // loop through the timers in the queue, cancelling each one
+ for (ACE_Timer_Node_T <ACE_Event_Handler *> *node;
+ (node = queue_->timer_queue ()->get_first ()) != 0;
+ )
+ queue_->timer_queue ()->cancel (node->get_timer_id (), 0, 0);
+
+ return 0;
+}
+
+// Constructor.
+
+BPR_Handler_Base::BPR_Handler_Base (Bounded_Packet_Relay &relay,
+ Thread_Timer_Queue &queue)
+ : relay_ (relay),
+ queue_ (queue)
+{
+}
+
+// Destructor.
+
+BPR_Handler_Base::~BPR_Handler_Base (void)
+{
+}
+
+// Helper method: clears all timers.
+
+int
+BPR_Handler_Base::clear_all_timers (void *)
+{
+ // Loop through the timers in the queue, cancelling each one.
+
+ for (ACE_Timer_Node_T <ACE_Event_Handler *> *node;
+ (node = queue_.timer_queue ()->get_first ()) != 0;
+ )
+ queue_.timer_queue ()->cancel (node->get_timer_id (), 0, 0);
+ // queue_.cancel (node->get_timer_id (), 0);
+
+ // Invoke the handler's (virtual) destructor
+ delete this;
+
+ return 0;
+}
+
+// Constructor.
+
+Send_Handler::Send_Handler (u_long send_count,
+ const ACE_Time_Value &duration,
+ Bounded_Packet_Relay &relay,
+ Thread_Timer_Queue &queue,
+ Thread_Bounded_Packet_Relay_Driver &driver)
+ : BPR_Handler_Base (relay, queue),
+ send_count_ (send_count),
+ duration_ (duration),
+ driver_ (driver)
+{
+}
+
+// Destructor.
+
+Send_Handler::~Send_Handler (void)
+{
+}
+
+// Call back hook.
+
+int
+Send_Handler::handle_timeout (const ACE_Time_Value &,
+ const void *)
+{
+ switch (relay_.send_input ())
+ {
+ case 0:
+ // Decrement count of packets to relay.
+ --send_count_;
+ /* Fall through to next case. */
+ case 1:
+ if (send_count_ > 0)
+ {
+ // Enqueue a deferred callback to the reregister command.
+ SEND_HANDLER_CMD *re_register_callback_;
+ ACE_NEW_RETURN (re_register_callback_,
+ SEND_HANDLER_CMD (*this,
+ &Send_Handler::reregister),
+ -1);
+ return queue_.enqueue_command (re_register_callback_);
+ }
+ else
+ {
+ // All packets are sent, time to end the transmission, redisplay
+ // the user menu, cancel any other timers, and go away.
+ relay_.end_transmission (Bounded_Packet_Relay::COMPLETED);
+ driver_.display_menu ();
+
+ // Enqueue a deferred callback to the clear_all_timers command.
+ HANDLER_CMD *clear_timers_callback_;
+ ACE_NEW_RETURN (clear_timers_callback_,
+ HANDLER_CMD (*this,
+ &BPR_Handler_Base::clear_all_timers),
+ -1);
+ return queue_.enqueue_command (clear_timers_callback_);
+ }
+ /* NOTREACHED */
+ default:
+ return -1;
+ }
+}
+
+// Cancellation hook.
+
+int
+Send_Handler::cancelled (void)
+{
+ delete this;
+ return 0;
+}
+
+// Helper method: re-registers this timer
+
+int
+Send_Handler::reregister (void *)
+{
+ // Re-register the handler for a new timeout.
+ if (queue_.schedule (this,
+ 0,
+ duration_ + ACE_OS::gettimeofday ()) < 0)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Send_Handler::reregister: "
+ "failed to reschedule send handler"),
+ -1);
+
+ return 0;
+}
+
+
+// Constructor.
+
+Termination_Handler::Termination_Handler (Bounded_Packet_Relay &relay,
+ Thread_Timer_Queue &queue,
+ Thread_Bounded_Packet_Relay_Driver &driver)
+ : BPR_Handler_Base (relay, queue),
+ driver_ (driver)
+{
+}
+
+// Destructor.
+
+Termination_Handler::~Termination_Handler (void)
+{
+}
+
+// Call back hook.
+
+int
+Termination_Handler::handle_timeout (const ACE_Time_Value &,
+ const void *)
+{
+ // Transmission timed out, so end the transmission, display the user
+ // menu, and register a callback to clear the timer queue and then
+ // make this object go away.
+ relay_.end_transmission (Bounded_Packet_Relay::TIMED_OUT);
+ driver_.display_menu ();
+
+ // Enqueue a deferred callback to the clear_all_timers command.
+ HANDLER_CMD *clear_timers_callback_;
+ ACE_NEW_RETURN (clear_timers_callback_,
+ HANDLER_CMD (*this,
+ &BPR_Handler_Base::clear_all_timers),
+ -1);
+ return queue_.enqueue_command (clear_timers_callback_);
+}
+
+// Cancellation hook
+
+int
+Termination_Handler::cancelled (void)
+{
+ delete this;
+ return 0;
+}
+
+// Constructor.
+
+Thread_Bounded_Packet_Relay_Driver::Thread_Bounded_Packet_Relay_Driver (Bounded_Packet_Relay *relay)
+ : input_task_ (relay, &timer_queue_, *this)
+{
+}
+
+// Destructor.
+
+Thread_Bounded_Packet_Relay_Driver::~Thread_Bounded_Packet_Relay_Driver (void)
+{
+}
+
+// Display the user menu.
+
+int
+Thread_Bounded_Packet_Relay_Driver::display_menu (void)
+{
+ static char menu[] =
+ "\n\n Options:\n"
+ " ----------------------------------------------------------------------\n"
+ " 1 <number of packets to relay in one transmission = %d>\n"
+ " min = 1 packet.\n"
+ " 2 <input packet arrival period (in usec) = %d>\n"
+ " min = 1.\n"
+ " 3 <output packet transmission period (in usec) = %d>\n"
+ " min = 1.\n"
+ " 4 <limit on duration of transmission (in usec) = %d>\n"
+ " min = 1, no limit = 0.\n"
+ " 5 <logging level flags = %d>\n"
+ " no logging = 0,\n"
+ " log packets created by input device = 1,\n"
+ " log packets consumed by output device = 2,\n"
+ " logging options 1,2 = 3,\n"
+ " print contents of packets consumed by output put device = 4,\n"
+ " logging options 1,4 = 5,\n"
+ " logging options 2,4 = 6,\n"
+ " logging options 1,2,4 = 7.\n"
+ " ----------------------------------------------------------------------\n"
+ " 6 - runs a transmission using the current settings\n"
+ " 7 - cancels a transmission (if there is one running)\n"
+ " 8 - reports statistics from the most recent transmission\n"
+ " 9 - quits the program\n"
+ " ----------------------------------------------------------------------\n"
+ " Please enter your choice: ";
+
+ ACE_DEBUG ((LM_DEBUG,
+ menu,
+ this->packet_count (),
+ this->arrival_period (),
+ this->send_period (),
+ this->duration_limit (),
+ this->logging_level ()));
+
+ return 0;
+}
+
+// Initialize the driver.
+
+int
+Thread_Bounded_Packet_Relay_Driver::init (void)
+{
+ // Initialize the <Command> objects with their corresponding
+ // methods from <User_Input_Task>.
+ ACE_NEW_RETURN (packet_count_cmd_,
+ DRIVER_CMD (input_task_,
+ &User_Input_Task::set_packet_count),
+ -1);
+ ACE_NEW_RETURN (arrival_period_cmd_,
+ DRIVER_CMD (input_task_,
+ &User_Input_Task::set_arrival_period),
+ -1);
+ ACE_NEW_RETURN (transmit_period_cmd_,
+ DRIVER_CMD (input_task_,
+ &User_Input_Task::set_send_period),
+ -1);
+ ACE_NEW_RETURN (duration_limit_cmd_,
+ DRIVER_CMD (input_task_,
+ &User_Input_Task::set_duration_limit),
+ -1);
+ ACE_NEW_RETURN (logging_level_cmd_,
+ DRIVER_CMD (input_task_,
+ &User_Input_Task::set_logging_level),
+ -1);
+ ACE_NEW_RETURN (run_transmission_cmd_,
+ DRIVER_CMD (input_task_,
+ &User_Input_Task::run_transmission),
+ -1);
+ ACE_NEW_RETURN (cancel_transmission_cmd_,
+ DRIVER_CMD (input_task_,
+ &User_Input_Task::end_transmission),
+ -1);
+ ACE_NEW_RETURN (report_stats_cmd_,
+ DRIVER_CMD (input_task_,
+ &User_Input_Task::report_stats),
+ -1);
+ ACE_NEW_RETURN (shutdown_cmd_,
+ DRIVER_CMD (input_task_,
+ &User_Input_Task::shutdown),
+ -1);
+ if (this->input_task_.activate () == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "cannot activate input task"),
+ -1);
+ else if (this->timer_queue_.activate () == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "cannot activate timer queue"),
+ -1);
+ else if (ACE_Thread_Manager::instance ()->wait () == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "wait on Thread_Manager failed"),
+ -1);
+ return 0;
+}
+
+// Run the driver
+
+int
+Thread_Bounded_Packet_Relay_Driver::run (void)
+{
+ this->init ();
+ return 0;
+}
+
diff --git a/ACE/examples/Bounded_Packet_Relay/Thread_Bounded_Packet_Relay.h b/ACE/examples/Bounded_Packet_Relay/Thread_Bounded_Packet_Relay.h
new file mode 100644
index 00000000000..ccd5782b487
--- /dev/null
+++ b/ACE/examples/Bounded_Packet_Relay/Thread_Bounded_Packet_Relay.h
@@ -0,0 +1,400 @@
+/* -*- C++ -*- */
+// $Id$
+
+// ============================================================================
+//
+// = LIBRARY
+// examples
+//
+// = FILENAME
+// Thread_Bounded_Packet_Relay.h
+//
+// = DESCRIPTION
+// This code provides a thread based implementation
+// of the bounded packet relay example.
+//
+// = AUTHORS
+// Chris Gill <cdgill@cs.wustl.edu> and
+// Douglas C. Schmidt <schmidt@cs.wustl.edu>
+//
+// Based on the Timer Queue Test example written by
+//
+// Carlos O'Ryan <coryan@cs.wustl.edu> and
+// Douglas C. Schmidt <schmidt@cs.wustl.edu> and
+// Sergio Flores-Gaitan <sergio@cs.wustl.edu>
+//
+// ============================================================================
+
+#ifndef _THREAD_BOUNDED_PACKET_RELAY_H_
+#define _THREAD_BOUNDED_PACKET_RELAY_H_
+
+#include "ace/Functor_T.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/Task.h"
+#include "ace/Timer_Heap_T.h"
+#include "ace/Timer_Queue_Adapters.h"
+#include "BPR_Drivers.h"
+
+// These typedefs ensure that we use the minimal amount of locking
+// necessary.
+typedef ACE_Event_Handler_Handle_Timeout_Upcall<ACE_Null_Mutex>
+ Upcall;
+typedef ACE_Timer_Heap_T<ACE_Event_Handler *,
+ Upcall,
+ ACE_Null_Mutex>
+ Timer_Heap;
+typedef ACE_Timer_Heap_Iterator_T<ACE_Event_Handler *,
+ Upcall,
+ ACE_Null_Mutex>
+ Timer_Heap_Iterator;
+typedef ACE_Thread_Timer_Queue_Adapter<Timer_Heap>
+ Thread_Timer_Queue;
+
+// Forward declaration.
+class Thread_Bounded_Packet_Relay_Driver;
+
+class Text_Input_Device_Wrapper : public Input_Device_Wrapper_Base
+{
+ // = TITLE
+ // Defines a wrapper for a simple active looping text input
+ // pseudo-device.
+ //
+ // = DESCRIPTION
+ // The wrapper is an active object, running in its own thread,
+ // and uses a reactor to generate timeouts. When a timeout
+ // occurs, the wrapper calls its concrete message creation
+ // method. The wrapper then calls its base class message send
+ // method to forward the message to the receiver.
+ //
+ // A more sophisticated version of this class would use the
+ // reactive capabilities as well as the timeout generating
+ // capabilities of the reactor, multiplexing several input
+ // streams. Comments to this effect appear in the definition of
+ // the event loop method.
+public:
+
+ // = Enumerated logging level flags
+ enum Logging_Flags {NO_LOGGING = 0,
+ LOG_MSGS_CREATED = 1};
+
+ // = Initialization and termination methods.
+ Text_Input_Device_Wrapper (ACE_Thread_Manager *input_task_mgr,
+ size_t read_length,
+ const char* text,
+ int logging = 0);
+ // Constructor.
+
+ virtual ~Text_Input_Device_Wrapper (void);
+ // Destructor.
+
+ virtual int modify_device_settings (void *logging);
+ // Modifies device settings based on passed pointer to a u_long.
+ // Turns logging on if u_long is non-zero, off if u_long is zero,
+ // and does nothing if the pointer is null.
+
+protected:
+ virtual ACE_Message_Block *create_input_message (void);
+ // Creates a new message block, carrying data read from the
+ // underlying input device.
+
+private:
+ size_t read_length_;
+ // Length of the buffer into which to "read".
+
+ const char *text_;
+ // Text to "read" into the buffer.
+
+ size_t index_;
+ // Index into the string.
+
+ int logging_;
+ // This value is 0 if logging is turned off, non-zero otherwise
+
+ u_long packet_count_;
+ // This value holds a count of packets created.
+
+};
+
+class Text_Output_Device_Wrapper : public Output_Device_Wrapper_Base
+{
+ // = TITLE
+ // Implements a simple wrapper for a output pseudo-device.
+ //
+ // = DESCRIPTION
+ // Data from the passed output message is printed to the standard
+ // output stream, if logging is turned on.
+public:
+
+ // = Enumerated logging level flags
+ enum Logging_Flags {NO_LOGGING = 0,
+ LOG_MSGS_RCVD = 2,
+ PRINT_MSGS_RCVD = 4};
+
+ Text_Output_Device_Wrapper (int logging = 0);
+ // Default constructor.
+
+ // = Command Accessible Entry Points
+
+ virtual int write_output_message (void *message);
+ // Consumes and possibly prints out the passed message.
+
+ virtual int modify_device_settings (void *logging);
+ // Modifies device settings based on passed pointer to a u_long.
+ // Turns logging on if u_long is non-zero, off if u_long is zero,
+ // and does nothing if the pointer is null.
+
+private:
+
+ int logging_;
+ // This value holds the logging level.
+
+ u_long packet_count_;
+ // This value holds a count of packets received.
+
+};
+
+class User_Input_Task : public ACE_Task_Base
+{
+ // = TITLE
+ // Read user actions on the Timer_Queue from stdin.
+ //
+ // = DESCRIPTION
+ // This class reads user input from stdin. The commands allow
+ // the control of a Timer_Queue, which is dispatched by another
+ // thread.
+public:
+
+ // = Trait for command accessible entry points.
+
+ typedef int (User_Input_Task::*ACTION) (void *);
+
+ User_Input_Task (Bounded_Packet_Relay *relay,
+ Thread_Timer_Queue *queue,
+ Thread_Bounded_Packet_Relay_Driver &timer_queue_driver);
+ // Constructor.
+
+ virtual ~User_Input_Task (void);
+ // Destructor.
+
+ virtual int svc (void);
+ // This method runs the event loop in the new thread.
+
+ // = Some helper methods.
+
+ int set_packet_count (void *);
+ // Sets the number of packets for the next transmission.
+
+ int set_arrival_period (void *);
+ // Sets the input device packet arrival period (usecs) for the next
+ // transmission.
+
+ int set_send_period (void *);
+ // Sets the period between output device sends (usecs) for the next
+ // transmission.
+
+ int set_duration_limit (void *);
+ // Sets a limit on the transmission duration (usecs).
+
+ int set_logging_level (void *);
+ // Sets logging level (0 or 1) for output device for the next
+ // transmission.
+
+ int run_transmission (void *);
+ // Runs the next transmission (if one is not in progress).
+
+ int end_transmission (void *);
+ // Ends the current transmission (if one is in progress).
+
+ int report_stats (void *);
+ // Reports statistics for the previous transmission (if one is not
+ // in progress).
+
+ int shutdown (void *);
+ // Shuts down the task.
+
+ int clear_all_timers (void);
+ // Helper method: clears all timers.
+
+private:
+ const int usecs_;
+ // How many microseconds are in a second.
+
+ Bounded_Packet_Relay *relay_;
+ // The bounded packet relay.
+
+ Thread_Timer_Queue *queue_;
+ // The timer queue implementation.
+
+ Thread_Bounded_Packet_Relay_Driver &driver_;
+ // The thread timer queue test driver.
+};
+
+class BPR_Handler_Base : public ACE_Event_Handler
+{
+ // = TITLE
+ // Base event handler class for bounded packet relay example.
+ //
+ // = DESCRIPTION
+ // The base class provides a helper method that derived classes
+ // can register as a deferred execution callback that will cancel
+ // all timers in the underlying timer queue, and then delete "this".
+ //
+public:
+
+ // = Trait for command accessible entry points.
+
+ typedef int (BPR_Handler_Base::*ACTION) (void *);
+
+
+ BPR_Handler_Base (Bounded_Packet_Relay &relay,
+ Thread_Timer_Queue &queue);
+ // Constructor.
+
+ virtual ~BPR_Handler_Base (void);
+ // Destructor.
+
+ // = Command accessible entry points.
+
+ virtual int clear_all_timers (void *);
+ // Helper method: clears all timers.
+
+protected:
+ Bounded_Packet_Relay &relay_;
+ // Stores a reference to the relay object on which to invoke
+ // the appropritate calls when the timer expires.
+
+ Thread_Timer_Queue &queue_;
+ // Store a reference to the timer queue, in which to re-register
+ // the send timer and handler if there are still sends to perform.
+};
+
+class Send_Handler;
+
+class Send_Handler : public BPR_Handler_Base
+{
+ // = TITLE
+ // Event handler for message send timeout events.
+ //
+ // = DESCRIPTION
+ // The <handle_timeout> hook method calls the relay's send
+ // method and decrements its count of messages to send.
+ // If there are still messages to send, it re-registers itself
+ // with the timer queue. Otherwise it calls the relay's end
+ // transmission method, and registers a deferred execution
+ // callback to clear the timer queue, and then delete "this".
+public:
+
+ // = Trait for command accessible entry points.
+
+ typedef int (Send_Handler::*ACTION) (void *);
+
+ Send_Handler (u_long send_count,
+ const ACE_Time_Value &duration,
+ Bounded_Packet_Relay &relay,
+ Thread_Timer_Queue &queue,
+ Thread_Bounded_Packet_Relay_Driver &driver);
+ // Constructor.
+
+ virtual ~Send_Handler (void);
+ // Destructor.
+
+ virtual int handle_timeout (const ACE_Time_Value &current_time,
+ const void *arg);
+ // Call back hook.
+
+ virtual int cancelled (void);
+ // Cancellation hook.
+
+ // = Command accessible entry points.
+
+ virtual int reregister (void *timeout);
+ // Helper method: re-registers this handler.
+
+private:
+
+ u_long send_count_;
+ // Count of the number of messages to send from the
+ // relay object to the output device object.
+
+ ACE_Time_Value duration_;
+ // Stores the expected duration until expiration, and is used to
+ // re-register the handler if there are still sends to perform.
+
+ Thread_Bounded_Packet_Relay_Driver &driver_;
+ // Reference to the driver that will redisplay the user input menu.
+};
+
+class Termination_Handler : public BPR_Handler_Base
+{
+ // = TITLE
+ // Event handler for end transmission timeout events.
+ //
+ // = DESCRIPTION
+ // The <handle_timeout> hook method calls the relay's end
+ // transmission method, then registers a deferred execution
+ // callback to clear all timers and then delete "this".
+public:
+ Termination_Handler (Bounded_Packet_Relay &relay,
+ Thread_Timer_Queue &queue,
+ Thread_Bounded_Packet_Relay_Driver &driver);
+ // Constructor.
+
+ virtual ~Termination_Handler (void);
+ // Destructor.
+
+ virtual int handle_timeout (const ACE_Time_Value &current_time,
+ const void *arg);
+ // Call back hook.
+
+ virtual int cancelled (void);
+ // Cancellation hook.
+
+private:
+ Thread_Bounded_Packet_Relay_Driver &driver_;
+ // Reference to the driver that will redisplay the user input menu.
+};
+
+class Thread_Bounded_Packet_Relay_Driver : public Bounded_Packet_Relay_Driver <Thread_Timer_Queue>
+{
+ // = TITLE
+ // Implements an example application that exercises
+ // <Thread_Timer_Queue> timer queue.
+ //
+ // = DESCRIPTION
+ // This class implements a simple test driver for the
+ // <Thread_Timer_Queue>. The <display_menu> hook method is
+ // called from the base class to print a menu specific to the
+ // thread implementation of the timer queue.
+public:
+
+ // = Trait for commands issued from this driver
+
+ typedef ACE_Command_Callback<User_Input_Task, User_Input_Task::ACTION> MYCOMMAND;
+
+ // = Initialization and termination methods.
+
+ Thread_Bounded_Packet_Relay_Driver (Bounded_Packet_Relay *relay);
+ // Constructor.
+
+ virtual ~Thread_Bounded_Packet_Relay_Driver (void);
+ // Destructor.
+
+ virtual int display_menu (void);
+ // Displays the user menu.
+
+ virtual int init (void);
+ // Initializes the driver.
+
+ virtual int run (void);
+ // Run the driver.
+
+private:
+ User_Input_Task input_task_;
+ // User input task, subclassed from ACE_Task.
+};
+
+#endif /* _THREAD_BOUNDED_PACKET_RELAY_H_ */
diff --git a/ACE/examples/Bounded_Packet_Relay/bpr_thread.cpp b/ACE/examples/Bounded_Packet_Relay/bpr_thread.cpp
new file mode 100644
index 00000000000..0a564ecd2a5
--- /dev/null
+++ b/ACE/examples/Bounded_Packet_Relay/bpr_thread.cpp
@@ -0,0 +1,122 @@
+// $Id$
+
+// ============================================================================
+//
+// = LIBRARY
+// examples
+//
+// = FILENAME
+// bpr_thread.cpp
+//
+// = DESCRIPTION
+// Exercises drivers for a bounded packet relay, based on threaded timer queues.
+//
+// = AUTHORS
+// Chris Gill <cdgill@cs.wustl.edu> and
+// Douglas C. Schmidt <schmidt@cs.wustl.edu>
+//
+// Based on the Timer Queue Test example written by
+//
+// Carlos O'Ryan <coryan@cs.wustl.edu> and
+// Douglas C. Schmidt <schmidt@cs.wustl.edu> and
+// Sergio Flores-Gaitan <sergio@cs.wustl.edu>
+//
+// ============================================================================
+
+// The following #pragma is needed to disable a warning that occurs
+// in MSVC 6 due to the overly long debugging symbols generated for
+// the std::auto_ptr<Timer_Queue_Test_Driver<...> > template
+// instance used by some of the methods in this file.
+#ifdef _MSC_VER
+# pragma warning(disable: 4786) /* identifier was truncated to '255'
+ characters in the browser
+ information */
+#endif /* _MSC_VER */
+
+#include "ace/Auto_Ptr.h"
+#include "Thread_Bounded_Packet_Relay.h"
+
+ACE_RCSID (Bounded_Packet_Relay,
+ bpr_thread,
+ "$Id$")
+
+typedef Bounded_Packet_Relay_Driver<Thread_Timer_Queue>
+ THREAD_BOUNDED_PACKET_RELAY_DRIVER;
+
+typedef ACE_Command_Callback<Bounded_Packet_Relay,Bounded_Packet_Relay::ACTION>
+ INPUT_CALLBACK;
+
+// A snippet from Andrew Marvell (Oliver Cromwell's poet laureate)
+static const char input_text [] =
+"But ever at my back I hear\n"
+" Time's winged chariot hurrying near.";
+
+int
+ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ // Construct a new thread manager for the input device task. Auto
+ // ptr ensures memory is freed when we exit this scope.
+ ACE_Thread_Manager *input_task_mgr;
+ ACE_NEW_RETURN (input_task_mgr,
+ ACE_Thread_Manager,
+ -1);
+ auto_ptr <ACE_Thread_Manager> mgr (input_task_mgr);
+
+ // Construct a new input device wrapper. Auto ptr ensures memory is
+ // freed when we exit this scope.
+ Text_Input_Device_Wrapper *input_device;
+ ACE_NEW_RETURN (input_device,
+ Text_Input_Device_Wrapper (input_task_mgr,
+ sizeof (input_text),
+ input_text),
+ -1);
+ auto_ptr <Text_Input_Device_Wrapper> input (input_device);
+
+ // Construct a new output device wrapper. Auto ptr ensures memory
+ // is freed when we exit this scope.
+ Text_Output_Device_Wrapper *output_device;
+ ACE_NEW_RETURN (output_device,
+ Text_Output_Device_Wrapper,
+ -1);
+ auto_ptr <Text_Output_Device_Wrapper> output (output_device);
+
+ // Construct a new bounded packet relay. Auto ptr ensures memory is
+ // freed when we exit this scope.
+ Bounded_Packet_Relay *packet_relay;
+ ACE_NEW_RETURN (packet_relay,
+ Bounded_Packet_Relay (input_task_mgr,
+ input_device,
+ output_device),
+ -1);
+ auto_ptr <Bounded_Packet_Relay> relay (packet_relay);
+
+ // Construct a receive input callback command for the relay, and register
+ // it with the input device. Auto ptr ensures memory is freed when we exit
+ // this scope.
+ INPUT_CALLBACK *input_callback;
+ ACE_NEW_RETURN (input_callback,
+ INPUT_CALLBACK (*packet_relay,
+ &Bounded_Packet_Relay::receive_input),
+ -1);
+ auto_ptr <INPUT_CALLBACK> callback (input_callback);
+ if (input_device->set_send_input_msg_cmd (input_callback) < 0)
+ {
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "failed to register input callback"),
+ -1);
+ }
+
+ // Construct a new bounded packet relay driver. Auto ptr ensures
+ // memory is freed when we exit this scope.
+ THREAD_BOUNDED_PACKET_RELAY_DRIVER *tbprd;
+
+ ACE_NEW_RETURN (tbprd,
+ Thread_Bounded_Packet_Relay_Driver (packet_relay),
+ -1);
+
+ auto_ptr <THREAD_BOUNDED_PACKET_RELAY_DRIVER> driver (tbprd);
+
+ return driver->run ();
+ // All dynamically allocated memory is released when main() returns.
+}
+
diff --git a/ACE/examples/C++NPv1/.cvsignore b/ACE/examples/C++NPv1/.cvsignore
new file mode 100644
index 00000000000..7735c154a0c
--- /dev/null
+++ b/ACE/examples/C++NPv1/.cvsignore
@@ -0,0 +1,14 @@
+RTTPC_logging_server
+RTTPC_logging_server
+iterative_logging_server
+iterative_logging_server
+logging_client
+logging_client
+ppc_logging_server
+ppc_logging_server
+reactive_logging_server
+reactive_logging_server
+reactive_logging_server_ex
+reactive_logging_server_ex
+tpc_logging_server
+tpc_logging_server
diff --git a/ACE/examples/C++NPv1/C++NPv1.mpc b/ACE/examples/C++NPv1/C++NPv1.mpc
new file mode 100644
index 00000000000..2cc6967e831
--- /dev/null
+++ b/ACE/examples/C++NPv1/C++NPv1.mpc
@@ -0,0 +1,70 @@
+// -*- MPC -*-
+// $Id$
+
+project(*Iterative_Logging_Server) : aceexe {
+ avoids += uses_wchar ace_for_tao
+ exename = iterative_logging_server
+ Source_Files {
+ Iterative_Logging_Server.cpp
+ Logging_Server.cpp
+ Logging_Handler.cpp
+ }
+}
+
+project(*Logging_Client) : aceexe {
+ avoids += uses_wchar
+ exename = logging_client
+ Source_Files {
+ Logging_Client.cpp
+ }
+}
+
+project(*PPC_Logging_Server) : aceexe {
+ avoids += uses_wchar ace_for_tao
+ exename = ppc_logging_server
+ Source_Files {
+ Process_Per_Connection_Logging_Server.cpp
+ Logging_Server.cpp
+ Logging_Handler.cpp
+ }
+}
+
+project(*Reactive_Logging_Server) : aceexe {
+ avoids += uses_wchar ace_for_tao
+ exename = reactive_logging_server
+ Source_Files {
+ Reactive_Logging_Server.cpp
+ Logging_Server.cpp
+ Logging_Handler.cpp
+ }
+}
+
+project(*Reactive_Logging_Server_Ex) : aceexe {
+ avoids += uses_wchar ace_for_tao
+ exename = reactive_logging_server_ex
+ Source_Files {
+ Reactive_Logging_Server_Ex.cpp
+ Logging_Server.cpp
+ Logging_Handler.cpp
+ }
+}
+
+project(*RTTPC_Logging_Server) : aceexe {
+ avoids += uses_wchar ace_for_tao
+ exename = RTTPC_logging_server
+ Source_Files {
+ RT_Thread_Per_Connection_Logging_Server.cpp
+ Logging_Server.cpp
+ Logging_Handler.cpp
+ }
+}
+
+project(*TPC_Logging_Server) : aceexe {
+ avoids += uses_wchar ace_for_tao
+ exename = tpc_logging_server
+ Source_Files {
+ Thread_Per_Connection_Logging_Server.cpp
+ Logging_Server.cpp
+ Logging_Handler.cpp
+ }
+}
diff --git a/ACE/examples/C++NPv1/Iterative_Logging_Server.cpp b/ACE/examples/C++NPv1/Iterative_Logging_Server.cpp
new file mode 100644
index 00000000000..f4c28f08da7
--- /dev/null
+++ b/ACE/examples/C++NPv1/Iterative_Logging_Server.cpp
@@ -0,0 +1,17 @@
+/*
+** $Id$
+**
+** Copyright 2001 Addison Wesley. All Rights Reserved.
+*/
+
+#include "ace/Log_Msg.h"
+#include "Iterative_Logging_Server.h"
+
+int main (int argc, char *argv[])
+{
+ Iterative_Logging_Server server;
+
+ if (server.run (argc, argv) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "server.run()"), 1);
+ return 0;
+}
diff --git a/ACE/examples/C++NPv1/Iterative_Logging_Server.h b/ACE/examples/C++NPv1/Iterative_Logging_Server.h
new file mode 100644
index 00000000000..f811f98c7ce
--- /dev/null
+++ b/ACE/examples/C++NPv1/Iterative_Logging_Server.h
@@ -0,0 +1,64 @@
+/*
+** $Id$
+**
+** Copyright 2001 Addison Wesley. All Rights Reserved.
+*/
+
+#ifndef _ITERATIVE_LOGGING_SERVER_H
+#define _ITERATIVE_LOGGING_SERVER_H
+
+#include "ace/FILE_IO.h"
+#include "ace/INET_Addr.h"
+#include "ace/Log_Msg.h"
+
+#include "Logging_Handler.h"
+#include "Logging_Server.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+class ACE_SOCK_Stream;
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+class Iterative_Logging_Server : public Logging_Server
+{
+protected:
+ ACE_FILE_IO log_file_;
+ Logging_Handler logging_handler_;
+
+public:
+ Iterative_Logging_Server () : logging_handler_ (log_file_) {}
+
+ virtual ~Iterative_Logging_Server () { log_file_.close (); }
+
+ Logging_Handler &logging_handler () { return logging_handler_; }
+
+protected:
+ // Override inherited open() from Logging_Server
+ virtual int open (u_short port) {
+ if (make_log_file (log_file_) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "make_log_file()"), -1);
+ return Logging_Server::open (port);
+ }
+
+ virtual int handle_connections () {
+ ACE_INET_Addr logging_peer_addr;
+
+ if (acceptor ().accept (logging_handler_.peer (),
+ &logging_peer_addr) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "acceptor.accept()"), -1);
+
+ ACE_DEBUG ((LM_DEBUG, "Accepted connection from %s\n",
+ logging_peer_addr.get_host_name ()));
+ return 0;
+ }
+
+ virtual int handle_data (ACE_SOCK_Stream *) {
+ while (logging_handler_.log_record () != -1)
+ continue;
+
+ logging_handler_.close (); // Close the socket handle.
+ return 0;
+ }
+
+};
+
+#endif /* _ITERATIVE_LOGGING_SERVER_H */
diff --git a/ACE/examples/C++NPv1/Logging_Client.cpp b/ACE/examples/C++NPv1/Logging_Client.cpp
new file mode 100644
index 00000000000..40f2609f30a
--- /dev/null
+++ b/ACE/examples/C++NPv1/Logging_Client.cpp
@@ -0,0 +1,141 @@
+/*
+** $Id$
+**
+** Copyright 2001 Addison Wesley. All Rights Reserved.
+*/
+
+#include "ace/OS_NS_sys_time.h"
+#include "ace/CDR_Stream.h"
+#include "ace/INET_Addr.h"
+#include "ace/SOCK_Connector.h"
+#include "ace/SOCK_Stream.h"
+#include "ace/Log_Msg.h"
+#include "ace/Log_Record.h"
+#include "ace/OS_NS_unistd.h"
+
+// FUZZ: disable check_for_streams_include
+#include "ace/streams.h"
+
+#if defined (ACE_WIN32) && (!defined (ACE_HAS_STANDARD_CPP_LIBRARY) || \
+ (ACE_HAS_STANDARD_CPP_LIBRARY == 0) || \
+ defined (ACE_USES_OLD_IOSTREAMS))
+# include <stdio.h>
+#else
+# include <string>
+#endif
+
+class Logging_Client {
+private:
+ ACE_SOCK_Stream logging_peer_;
+
+public:
+ ACE_SOCK_Stream &peer () { return logging_peer_; }
+
+ int send (const ACE_Log_Record &log_record) {
+ // Serialize the log record using a CDR stream, allocate
+ // enough space for the complete <ACE_Log_Record>.
+ const size_t max_payload_size =
+ 4 // type()
+ + 8 // timestamp
+ + 4 // process id
+ + 4 // data length
+ + ACE_Log_Record::MAXLOGMSGLEN // data
+ + ACE_CDR::MAX_ALIGNMENT; // padding;
+
+ // Insert contents of <log_record> into payload stream.
+ ACE_OutputCDR payload (max_payload_size);
+ payload << log_record;
+
+ // Get the number of bytes used by the CDR stream.
+ ACE_CDR::ULong length = payload.total_length ();
+
+ // Send a header so the receiver can determine the byte
+ // order and size of the incoming CDR stream.
+ ACE_OutputCDR header (ACE_CDR::MAX_ALIGNMENT + 8);
+ header << ACE_OutputCDR::from_boolean (ACE_CDR_BYTE_ORDER);
+
+ // Store the size of the payload that follows
+ header << ACE_CDR::ULong (length);
+ // Use an iovec to send both buffer and payload simultaneously.
+ iovec iov[2];
+ iov[0].iov_base = header.begin ()->rd_ptr ();
+ iov[0].iov_len = 8;
+ iov[1].iov_base = payload.begin ()->rd_ptr ();
+ iov[1].iov_len = length;
+
+ // Send header and payload efficiently using "gather-write".
+ return logging_peer_.sendv_n (iov, 2);
+ }
+
+ ~Logging_Client () { logging_peer_.close (); }
+};
+
+
+int main (int argc, char *argv[])
+{
+ u_short logger_port = argc > 1 ? atoi (argv[1]) : 0;
+ const char *logger_host =
+ argc > 2 ? argv[2] : ACE_DEFAULT_SERVER_HOST;
+ int result;
+
+ ACE_INET_Addr server_addr;
+
+ if (logger_port != 0)
+ result = server_addr.set (logger_port, logger_host);
+ else
+ result = server_addr.set ("ace_logger", logger_host);
+ if (result == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, "lookup %s, %p\n",
+ logger_port == 0 ? "ace_logger" : argv[1],
+ logger_host), 1);
+
+ ACE_SOCK_Connector connector;
+ Logging_Client logging_client;
+
+ if (connector.connect (logging_client.peer (), server_addr) < 0)
+ ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "connect()"), 1);
+
+#if defined (ACE_WIN32) && (!defined (ACE_HAS_STANDARD_CPP_LIBRARY) || \
+ (ACE_HAS_STANDARD_CPP_LIBRARY == 0) || \
+ defined (ACE_USES_OLD_IOSTREAMS))
+ for (;;) {
+ char user_input[ACE_Log_Record::MAXLOGMSGLEN];
+ if (!gets (user_input))
+ break;
+
+ ACE_Time_Value now (ACE_OS::gettimeofday ());
+ ACE_Log_Record log_record (LM_INFO, now, ACE_OS::getpid ());
+ log_record.msg_data (user_input);
+ if (logging_client.send (log_record) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%p\n", "logging_client.send()"), 1);
+ }
+#else
+
+ // Limit the number of characters read on each record
+ cin.width (ACE_Log_Record::MAXLOGMSGLEN);
+
+ for (;;) {
+
+#if defined (ACE_USES_STD_NAMESPACE_FOR_STDCPP_LIB) && (ACE_USES_STD_NAMESPACE_FOR_STDCPP_LIB == 0)
+ string user_input;
+ getline (cin, user_input, '\n');
+#else
+ std::string user_input;
+ std::getline (cin, user_input, '\n');
+
+#endif
+
+ if (!cin || cin.eof ()) break;
+
+ ACE_Time_Value now (ACE_OS::gettimeofday ());
+ ACE_Log_Record log_record (LM_INFO, now, ACE_OS::getpid ());
+ log_record.msg_data (user_input.c_str ());
+ if (logging_client.send (log_record) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%p\n", "logging_client.send()"), 1);
+ }
+#endif
+
+ return 0; // Logging_Client destructor closes TCP connection.
+}
diff --git a/ACE/examples/C++NPv1/Logging_Handler.cpp b/ACE/examples/C++NPv1/Logging_Handler.cpp
new file mode 100644
index 00000000000..b24066fc208
--- /dev/null
+++ b/ACE/examples/C++NPv1/Logging_Handler.cpp
@@ -0,0 +1,110 @@
+/*
+** $Id$
+**
+** Copyright 2001 Addison Wesley. All Rights Reserved.
+*/
+
+#include "ace/ACE.h"
+#include "ace/CDR_Stream.h"
+#include "ace/INET_Addr.h"
+#include "ace/Log_Record.h"
+#include "ace/Message_Block.h"
+
+#include "Logging_Handler.h"
+
+// FUZZ: disable check_for_streams_include
+#include "ace/streams.h"
+
+#include "ace/os_include/os_netdb.h"
+
+int Logging_Handler::recv_log_record (ACE_Message_Block *&mblk)
+{
+ // Put <logging_peer>'s hostname in new message block.
+ ACE_INET_Addr peer_addr;
+ logging_peer_.get_remote_addr (peer_addr);
+ mblk = new ACE_Message_Block (MAXHOSTNAMELEN + 1);
+ peer_addr.get_host_name (mblk->wr_ptr (), MAXHOSTNAMELEN);
+ mblk->wr_ptr (strlen (mblk->wr_ptr ()) + 1); // Go past name
+
+ // Allocate a message block for the payload; initially at least
+ // large enough to hold the header, but needs some room for
+ // alignment.
+ ACE_Message_Block *payload =
+ new ACE_Message_Block (ACE_DEFAULT_CDR_BUFSIZE);
+ // Align the Message Block for a CDR stream
+ ACE_CDR::mb_align (payload);
+ if (logging_peer_.recv_n (payload->wr_ptr (), 8) == 8) {
+ payload->wr_ptr (8); // Reflect addition of 8 bytes
+
+ // Create a CDR stream to parse the 8-byte header.
+ ACE_InputCDR cdr (payload);
+
+ // Extract the byte-order and use helper methods to
+ // disambiguate octet, booleans, and chars.
+ ACE_CDR::Boolean byte_order;
+ cdr >> ACE_InputCDR::to_boolean (byte_order);
+
+ // Set the byte-order on the stream...
+ cdr.reset_byte_order (byte_order);
+
+ // Extract the length
+ ACE_CDR::ULong length;
+ cdr >> length;
+
+ // Ensure there's sufficient room for log record payload.
+ ACE_CDR::grow (payload, 8 + ACE_CDR::MAX_ALIGNMENT + length);
+
+ // Use <recv_n> to obtain the contents.
+ if (logging_peer_.recv_n (payload->wr_ptr (), length) > 0) {
+ payload->wr_ptr (length); // Reflect additional bytes
+ // Chain the payload to mblk via the contination field.
+ mblk->cont (payload);
+ return length;
+ }
+ }
+ // Error cases end up here, so we need to release the memory to
+ // prevent a leak.
+ payload->release ();
+ payload = 0;
+ mblk->release ();
+ mblk = 0;
+ return -1;
+}
+
+int
+Logging_Handler::write_log_record (ACE_Message_Block *mblk)
+{
+ // Peer hostname is in the <mblk> and the log record data
+ // is in its continuation.
+ if (log_file_.send_n (mblk) == -1)
+ return -1;
+ if (ACE::debug ()) {
+ // Build a CDR stream from the log record data.
+ ACE_InputCDR cdr (mblk->cont ());
+ ACE_CDR::Boolean byte_order;
+ ACE_CDR::ULong length;
+ // Extract the byte-order and length, ending up at the start
+ // of the log record itself. Use the byte order to properly
+ // set the CDR stream for extracting the contents.
+ cdr >> ACE_InputCDR::to_boolean (byte_order);
+ cdr.reset_byte_order (byte_order);
+ cdr >> length;
+ ACE_Log_Record log_record;
+ cdr >> log_record; // Finally extract the <ACE_log_record>.
+ log_record.print (mblk->rd_ptr (), 1, cerr);
+ }
+ return mblk->total_length ();
+}
+
+
+int Logging_Handler::log_record ()
+{
+ ACE_Message_Block *mblk = 0;
+ if (recv_log_record (mblk) == -1)
+ return -1;
+ else {
+ int result = write_log_record (mblk);
+ mblk->release (); // Free up the contents.
+ return result == -1 ? -1 : 0;
+ }
+}
diff --git a/ACE/examples/C++NPv1/Logging_Handler.h b/ACE/examples/C++NPv1/Logging_Handler.h
new file mode 100644
index 00000000000..6e0004212b3
--- /dev/null
+++ b/ACE/examples/C++NPv1/Logging_Handler.h
@@ -0,0 +1,55 @@
+/*
+** $Id$
+**
+** Copyright 2001 Addison Wesley. All Rights Reserved.
+*/
+
+#ifndef _LOGGING_HANDLER_H
+#define _LOGGING_HANDLER_H
+
+#include "ace/FILE_IO.h"
+#include "ace/SOCK_Stream.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+class ACE_Message_Block;
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+class Logging_Handler
+{
+protected:
+ ACE_FILE_IO &log_file_; // Reference to a log file.
+
+ ACE_SOCK_Stream logging_peer_; // Connected to the client.
+
+public:
+ // Initialization and termination methods.
+ Logging_Handler (ACE_FILE_IO &log_file): log_file_ (log_file) {}
+ Logging_Handler (ACE_FILE_IO &log_file,
+ ACE_HANDLE handle): log_file_ (log_file)
+ { logging_peer_.set_handle (handle); }
+ Logging_Handler (ACE_FILE_IO &log_file,
+ const ACE_SOCK_Stream &logging_peer)
+ : log_file_ (log_file), logging_peer_ (logging_peer) {}
+ int close () { return logging_peer_.close (); }
+
+ // Receive one log record from a connected client. Returns
+ // length of record on success and <mblk> contains the
+ // hostname, <mblk->cont()> contains the log record header
+ // (the byte order and the length) and the data. Returns -1 on
+ // failure or connection close.
+ int recv_log_record (ACE_Message_Block *&log_record);
+
+ // Write one record to the log file. The <mblk> contains the
+ // hostname and the <mblk->cont> contains the log record.
+ // Returns length of record written on success, or -1 on failure.
+ int write_log_record (ACE_Message_Block *log_record);
+
+ // Log one record by calling <recv_log_record> and
+ // <write_log_record>. Returns 0 on success and -1 on failure.
+ int log_record ();
+
+ // Accessor method.
+ ACE_SOCK_Stream &peer () { return logging_peer_; }
+};
+
+#endif /* _LOGGING_HANDLER_H */
diff --git a/ACE/examples/C++NPv1/Logging_Server.cpp b/ACE/examples/C++NPv1/Logging_Server.cpp
new file mode 100644
index 00000000000..c685412c769
--- /dev/null
+++ b/ACE/examples/C++NPv1/Logging_Server.cpp
@@ -0,0 +1,74 @@
+/*
+** $Id$
+**
+** Copyright 2001 Addison Wesley. All Rights Reserved.
+*/
+
+#include "ace/FILE_Addr.h"
+#include "ace/FILE_Connector.h"
+#include "ace/FILE_IO.h"
+#include "ace/INET_Addr.h"
+#include "ace/SOCK_Stream.h"
+#include "Logging_Server.h"
+#include "ace/OS_NS_string.h"
+#include "ace/os_include/os_netdb.h"
+
+int Logging_Server::run (int argc, char *argv[])
+{
+ if (open (argc > 1 ? atoi (argv[1]) : 0) == -1)
+ return -1;
+
+ for (;;) {
+ if (wait_for_multiple_events () == -1)
+ return -1;
+ if (handle_connections () == -1)
+ return -1;
+ if (handle_data () == -1)
+ return -1;
+ }
+
+ return 0;
+}
+
+
+int Logging_Server::open (u_short logger_port)
+{
+ ACE_INET_Addr server_addr;
+ int result;
+
+ if (logger_port != 0)
+ result = server_addr.set (logger_port,
+ (ACE_UINT32) INADDR_ANY);
+ else
+ result = server_addr.set ("ace_logger",
+ (ACE_UINT32) INADDR_ANY);
+ if (result == -1) return -1;
+
+ // Start listening, enable reuse of listen address for quick restarts.
+ return acceptor_.open (server_addr, 1);
+}
+
+
+int Logging_Server::make_log_file (ACE_FILE_IO &logging_file,
+ ACE_SOCK_Stream *logging_peer)
+{
+ char filename[MAXHOSTNAMELEN + sizeof (".log")];
+
+ if (logging_peer != 0) { // Use client's hostname as log file name.
+ ACE_INET_Addr logging_peer_addr;
+ logging_peer->get_remote_addr (logging_peer_addr);
+ logging_peer_addr.get_host_name (filename, MAXHOSTNAMELEN);
+ ACE_OS::strcat (filename, ".log");
+ }
+ else
+ ACE_OS::strcpy (filename, "logging_server.log");
+
+ ACE_FILE_Connector connector;
+ return connector.connect (logging_file,
+ ACE_FILE_Addr (filename),
+ 0, // No timeout.
+ ACE_Addr::sap_any, // Ignored.
+ 0, // Don't try to reuse the addr.
+ O_RDWR|O_CREAT|O_APPEND,
+ ACE_DEFAULT_FILE_PERMS);
+}
diff --git a/ACE/examples/C++NPv1/Logging_Server.h b/ACE/examples/C++NPv1/Logging_Server.h
new file mode 100644
index 00000000000..2c8624a11cb
--- /dev/null
+++ b/ACE/examples/C++NPv1/Logging_Server.h
@@ -0,0 +1,44 @@
+/*
+** $Id$
+**
+** Copyright 2001 Addison Wesley. All Rights Reserved.
+*/
+
+#ifndef _LOGGING_SERVER_H
+#define _LOGGING_SERVER_H
+
+#include "ace/FILE_IO.h"
+#include "ace/SOCK_Acceptor.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+class ACE_SOCK_Stream;
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+class Logging_Server
+{
+public:
+ // Template Method that runs logging server's event loop.
+ virtual int run (int argc, char *argv[]);
+
+protected:
+ // The following four methods are ``hooks'' that can be
+ // overridden by subclasses.
+ virtual int open (u_short port = 0);
+ virtual int wait_for_multiple_events () { return 0; }
+ virtual int handle_connections () = 0;
+ virtual int handle_data (ACE_SOCK_Stream * = 0) = 0;
+
+ // The following helper method can be used by the hook methods.
+ int make_log_file (ACE_FILE_IO &, ACE_SOCK_Stream * = 0);
+
+ // Close the socket endpoint.
+ virtual ~Logging_Server () { acceptor_.close (); }
+
+ // Accessor.
+ ACE_SOCK_Acceptor &acceptor () { return acceptor_; }
+
+private:
+ ACE_SOCK_Acceptor acceptor_; // Socket acceptor endpoint.
+};
+
+#endif /* _LOGGING_SERVER_H */
diff --git a/ACE/examples/C++NPv1/Makefile.am b/ACE/examples/C++NPv1/Makefile.am
new file mode 100644
index 00000000000..5c46ae7f00d
--- /dev/null
+++ b/ACE/examples/C++NPv1/Makefile.am
@@ -0,0 +1,191 @@
+## Process this file with automake to create Makefile.in
+##
+## $Id$
+##
+## This file was generated by MPC. Any changes made directly to
+## this file will be lost the next time it is generated.
+##
+## MPC Command:
+## /acebuilds/ACE_wrappers-repository/bin/mwc.pl -include /acebuilds/MPC/config -include /acebuilds/MPC/templates -feature_file /acebuilds/ACE_wrappers-repository/local.features -noreldefs -type automake -exclude build,Kokyu
+
+ACE_BUILDDIR = $(top_builddir)
+ACE_ROOT = $(top_srcdir)
+
+noinst_PROGRAMS =
+
+## Makefile.C++NPv1_Iterative_Logging_Server.am
+
+if !BUILD_ACE_FOR_TAO
+if !BUILD_USES_WCHAR
+noinst_PROGRAMS += iterative_logging_server
+
+iterative_logging_server_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+iterative_logging_server_SOURCES = \
+ Iterative_Logging_Server.cpp \
+ Logging_Handler.cpp \
+ Logging_Server.cpp \
+ Iterative_Logging_Server.h \
+ Logging_Handler.h \
+ Logging_Server.h
+
+iterative_logging_server_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+endif !BUILD_USES_WCHAR
+endif !BUILD_ACE_FOR_TAO
+
+## Makefile.C++NPv1_Logging_Client.am
+
+if !BUILD_USES_WCHAR
+noinst_PROGRAMS += logging_client
+
+logging_client_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+logging_client_SOURCES = \
+ Logging_Client.cpp \
+ Iterative_Logging_Server.h \
+ Logging_Handler.h \
+ Logging_Server.h \
+ Process_Per_Connection_Logging_Server.h \
+ RT_Thread_Per_Connection_Logging_Server.h \
+ Reactive_Logging_Server.h \
+ Reactive_Logging_Server_Ex.h \
+ Thread_Per_Connection_Logging_Server.h
+
+logging_client_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+endif !BUILD_USES_WCHAR
+
+## Makefile.C++NPv1_PPC_Logging_Server.am
+
+if !BUILD_ACE_FOR_TAO
+if !BUILD_USES_WCHAR
+noinst_PROGRAMS += ppc_logging_server
+
+ppc_logging_server_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+ppc_logging_server_SOURCES = \
+ Logging_Handler.cpp \
+ Logging_Server.cpp \
+ Process_Per_Connection_Logging_Server.cpp \
+ Logging_Handler.h \
+ Logging_Server.h \
+ Process_Per_Connection_Logging_Server.h
+
+ppc_logging_server_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+endif !BUILD_USES_WCHAR
+endif !BUILD_ACE_FOR_TAO
+
+## Makefile.C++NPv1_RTTPC_Logging_Server.am
+
+if !BUILD_ACE_FOR_TAO
+if !BUILD_USES_WCHAR
+noinst_PROGRAMS += RTTPC_logging_server
+
+RTTPC_logging_server_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+RTTPC_logging_server_SOURCES = \
+ Logging_Handler.cpp \
+ Logging_Server.cpp \
+ RT_Thread_Per_Connection_Logging_Server.cpp \
+ Logging_Handler.h \
+ Logging_Server.h \
+ RT_Thread_Per_Connection_Logging_Server.h
+
+RTTPC_logging_server_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+endif !BUILD_USES_WCHAR
+endif !BUILD_ACE_FOR_TAO
+
+## Makefile.C++NPv1_Reactive_Logging_Server.am
+
+if !BUILD_ACE_FOR_TAO
+if !BUILD_USES_WCHAR
+noinst_PROGRAMS += reactive_logging_server
+
+reactive_logging_server_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+reactive_logging_server_SOURCES = \
+ Logging_Handler.cpp \
+ Logging_Server.cpp \
+ Reactive_Logging_Server.cpp \
+ Logging_Handler.h \
+ Logging_Server.h \
+ Reactive_Logging_Server.h
+
+reactive_logging_server_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+endif !BUILD_USES_WCHAR
+endif !BUILD_ACE_FOR_TAO
+
+## Makefile.C++NPv1_Reactive_Logging_Server_Ex.am
+
+if !BUILD_ACE_FOR_TAO
+if !BUILD_USES_WCHAR
+noinst_PROGRAMS += reactive_logging_server_ex
+
+reactive_logging_server_ex_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+reactive_logging_server_ex_SOURCES = \
+ Logging_Handler.cpp \
+ Logging_Server.cpp \
+ Reactive_Logging_Server_Ex.cpp \
+ Logging_Handler.h \
+ Logging_Server.h \
+ Reactive_Logging_Server_Ex.h
+
+reactive_logging_server_ex_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+endif !BUILD_USES_WCHAR
+endif !BUILD_ACE_FOR_TAO
+
+## Makefile.C++NPv1_TPC_Logging_Server.am
+
+if !BUILD_ACE_FOR_TAO
+if !BUILD_USES_WCHAR
+noinst_PROGRAMS += tpc_logging_server
+
+tpc_logging_server_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+tpc_logging_server_SOURCES = \
+ Logging_Handler.cpp \
+ Logging_Server.cpp \
+ Thread_Per_Connection_Logging_Server.cpp \
+ Logging_Handler.h \
+ Logging_Server.h \
+ Thread_Per_Connection_Logging_Server.h
+
+tpc_logging_server_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+endif !BUILD_USES_WCHAR
+endif !BUILD_ACE_FOR_TAO
+
+## Clean up template repositories, etc.
+clean-local:
+ -rm -f *~ *.bak *.rpo *.sym lib*.*_pure_* core core.*
+ -rm -f gcctemp.c gcctemp so_locations *.ics
+ -rm -rf cxx_repository ptrepository ti_files
+ -rm -rf templateregistry ir.out
+ -rm -rf ptrepository SunWS_cache Templates.DB
diff --git a/ACE/examples/C++NPv1/Process_Per_Connection_Logging_Server.cpp b/ACE/examples/C++NPv1/Process_Per_Connection_Logging_Server.cpp
new file mode 100644
index 00000000000..54d936962aa
--- /dev/null
+++ b/ACE/examples/C++NPv1/Process_Per_Connection_Logging_Server.cpp
@@ -0,0 +1,180 @@
+/*
+** $Id$
+**
+** Copyright 2001 Addison Wesley. All Rights Reserved.
+*/
+
+#include "ace/Log_Msg.h"
+#include "ace/Process_Manager.h"
+#include "ace/Signal.h"
+#include "ace/OS_NS_string.h"
+#include "ace/os_include/os_fcntl.h"
+
+#include "Process_Per_Connection_Logging_Server.h"
+#include "Logging_Handler.h"
+
+#include <errno.h>
+
+namespace {
+ extern "C" void sigterm_handler (int /* signum */) { /* No-op. */ }
+}
+
+
+Logging_Process::Logging_Process (const char *prog_name,
+ const ACE_SOCK_Stream &logging_peer)
+ : logging_peer_ (logging_peer.get_handle ())
+{
+ ACE_OS::strcpy (prog_name_, prog_name);
+}
+
+// Set up the process options here. If the decision to do a fork
+// a no exec on POSIX needs to be changed, this is the only place
+// that needs to change (omit the creation_flags() call).
+// We request that the logging client's socket handle be passed
+// to the child process. The internals of ACE_Process insure that
+// it gets put on the command line if starting a new program image,
+// and that if it needed to be duplicated to accomplish that (such
+// as on Win32) it will get properly closed.
+// The process_name () call sets the program to run and is also used
+// for the fork() call on POSIX.
+// avoid_zombies has a real affect only on POSIX; it's harmless on Win32.
+// Setting the NO_EXEC creation flag is what prevents the exec() on
+// POSIX. It has no affect on Win32.
+int
+Logging_Process::prepare (ACE_Process_Options &options)
+{
+ if (options.pass_handle (logging_peer_.get_handle ()) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "pass_handle"), -1);
+ options.command_line ("%s", prog_name_);
+ options.avoid_zombies (1);
+ options.creation_flags (ACE_Process_Options::NO_EXEC);
+ return 0;
+}
+
+// Just delete the process object. If any handles needed to be
+// duplicated to be passed to the child, they'll get closed now
+// by the ACE_Process destructor.
+void
+Logging_Process::unmanage ()
+{
+ delete this;
+}
+
+
+int
+Process_Per_Connection_Logging_Server::handle_connections ()
+{
+ ACE_SOCK_Stream logging_peer;
+
+ // Block until a client connects.
+ if (acceptor ().accept (logging_peer) == -1)
+ return -1;
+
+ Logging_Process *logger =
+ new Logging_Process (prog_name_, logging_peer);
+ ACE_Process_Options options;
+ pid_t pid;
+ pid = ACE_Process_Manager::instance ()->spawn (logger,
+ options);
+ // If we came back with pid 0 from the spawn(), this is a
+ // POSIX fork system - we are in the child process. Handle the
+ // logging records, then exit.
+ if (pid == 0) {
+ acceptor().close ();
+ handle_data (&logging_peer);
+ delete logger;
+ ACE_OS::exit (0);
+ }
+ logging_peer.close ();
+ if (pid == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "spawn()"), -1);
+
+ // See if there are any child processes that have
+ // exited - reap their status and clean up handles held
+ // open while the child executed.
+ ACE_Process_Manager::instance ()->wait (0,
+ ACE_Time_Value::zero);
+ return 0;
+}
+
+int
+Process_Per_Connection_Logging_Server::handle_data (ACE_SOCK_Stream *client)
+{
+ // Disable non-blocking mode.
+ client->disable (ACE_NONBLOCK);
+ ACE_FILE_IO log_file;
+ make_log_file (log_file, client);
+ Logging_Handler logging_handler (log_file, *client);
+
+ while (logging_handler.log_record () != -1)
+ continue;
+
+ log_file.close ();
+ return 0;
+}
+
+
+int
+Process_Per_Connection_Logging_Server::run (int argc, char *argv[])
+{
+ ACE_OS::strncpy (prog_name_, argv[0], MAXPATHLEN);
+ prog_name_[MAXPATHLEN] = '\0'; // Ensure NUL-termination.
+ // If there are 2 command line arguments after prog_name_, this
+ // is a spawned worker process. Else run as the master.
+ if (argc == 3)
+ return run_worker (argc, argv); // Only on Win32.
+ else
+ return run_master (argc, argv);
+}
+
+int
+Process_Per_Connection_Logging_Server::run_master (int argc, char *argv[])
+{
+ u_short logger_port = 0;
+ if (argc == 2)
+ logger_port = atoi (argv[1]);
+ if (open (logger_port) == -1)
+ return -1;
+
+ for (;;)
+ if (handle_connections () == -1)
+ return -1;
+
+ return 0;
+}
+
+int
+Process_Per_Connection_Logging_Server::run_worker (int, char *argv[])
+{
+ int client_handle_i = atoi (argv[2]);
+ // Some compilers don't like reinterpret_casting an int to an int, so
+ // only do reinterpret_cast on Windows.
+#if defined (ACE_WIN32)
+ ACE_HANDLE client_handle =
+ reinterpret_cast<ACE_HANDLE> (client_handle_i);
+#else
+ ACE_HANDLE client_handle =
+ static_cast<ACE_HANDLE> (client_handle_i);
+#endif /* ACE_WIN32 */
+ ACE_SOCK_Stream client (client_handle);
+
+ handle_data (&client);
+ client.close ();
+ return 0;
+}
+
+
+int main (int argc, char *argv[])
+{
+ // Register to receive the <SIGTERM> signal.
+ ACE_Sig_Action sa ((ACE_SignalHandler)sigterm_handler,
+ SIGTERM);
+
+ Process_Per_Connection_Logging_Server server;
+
+ if (server.run (argc, argv) == -1 && errno != EINTR)
+ ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "server.run()"), 1);
+
+ // Barrier synchronization.
+ return ACE_Process_Manager::instance ()->wait ();
+}
diff --git a/ACE/examples/C++NPv1/Process_Per_Connection_Logging_Server.h b/ACE/examples/C++NPv1/Process_Per_Connection_Logging_Server.h
new file mode 100644
index 00000000000..4d64d764bfd
--- /dev/null
+++ b/ACE/examples/C++NPv1/Process_Per_Connection_Logging_Server.h
@@ -0,0 +1,53 @@
+/*
+** $Id$
+**
+** Copyright 2001 Addison Wesley. All Rights Reserved.
+*/
+
+#ifndef _PROCESS_PER_CONNECTION_LOGGING_SERVER_H
+#define _PROCESS_PER_CONNECTION_LOGGING_SERVER_H
+
+#include "ace/INET_Addr.h"
+#include "ace/Log_Record.h"
+#include "ace/Process.h"
+#include "ace/Process_Manager.h"
+#include "ace/SOCK_Acceptor.h"
+#include "ace/SOCK_Stream.h"
+#include "ace/Signal.h"
+#include "Logging_Server.h"
+
+class Logging_Process : public ACE_Process
+{
+public:
+ Logging_Process (const char *prog_name,
+ const ACE_SOCK_Stream &logging_peer);
+
+ virtual int prepare (ACE_Process_Options &options);
+ virtual void unmanage ();
+
+private:
+ Logging_Process (); // Force desired constructor to be used.
+
+ char prog_name_[MAXPATHLEN + 1];
+ ACE_SOCK_Stream logging_peer_;
+};
+
+
+class Process_Per_Connection_Logging_Server : public Logging_Server
+{
+protected:
+ char prog_name_[MAXPATHLEN + 1];
+
+protected:
+ virtual int handle_connections ();
+ virtual int handle_data (ACE_SOCK_Stream *client = 0);
+
+ int run_master (int argc, char *argv[]);
+ int run_worker (int argc, char *argv[]);
+
+public:
+ virtual int run (int argc, char *argv[]);
+
+};
+
+#endif /* _PROCESS_PER_CONNECTION_LOGGING_SERVER_H */
diff --git a/ACE/examples/C++NPv1/README b/ACE/examples/C++NPv1/README
new file mode 100644
index 00000000000..747fa24ecfc
--- /dev/null
+++ b/ACE/examples/C++NPv1/README
@@ -0,0 +1,73 @@
+(This is file $Id$)
+
+The files in this directory contain the source code from the book
+``C++ Network Programming: Mastering Complexity Using ACE and
+Patterns'' (C++NPv1) by Douglas C. Schmidt and Stephen D. Huston
+(Addison-Wesley 2001, ISBN 0-201-60464-7).
+
+We have compiled and run these files on the following platforms:
+
+ Sun Solaris 8 on SPARC using Sun Forte 6.
+ Redhat Linux 7.1 using g++ 2.96.
+ Microsoft Windows 2000 using Microsoft Visual C++ 6.
+
+You must have the ACE_ROOT environment variable set correctly to build
+these examples. ACE_ROOT must refer to the top-level ACE_wrappers
+directory. Please see $ACE_ROOT/ACE-INSTALL.html for instructions on
+how to build the ACE toolkit.
+
+Mapping Source Files to Book Chapters
+-------------------------------------
+
+The files in this directory map to the chapters in C++NPv1 as follows:
+
+Chapter 4 Logging_Client.h
+ Logging_Client.cpp
+ Logging_Handler.h
+ Logging_Handler.cpp
+ Iterative_Logging_Server.h
+ Iterative_Logging_Server.cpp
+
+Chapter 7 Reactive_Logging_Server.h
+ Reactive_Logging_Server.cpp
+ Reactive_Logging_Server_Ex.h
+ Reactive_Logging_Server_Ex.cpp
+
+Chapter 8 Process_Per_Connection_Logging_Server.h
+ Process_Per_Connection_Logging_Server.cpp
+
+Chapter 9 Thread_Per_Connection_Logging_Server.h
+ Thread_Per_Connection_Logging_Server.cpp
+ RT_Thread_Per_Connection_Logging_Server.h
+ RT_Thread_Per_Connection_Logging_Server.cpp
+
+Microsoft Visual C++ users:
+---------------------------
+
+The examples.dsw file is a Microsoft Visual C++ workspace file that
+contains projects for the individual programs. You can either build
+them separately, or use the Batch Build command to build multiple
+projects at once.
+
+All other users:
+----------------
+
+Assuming that your system is configured correctly, you should be able
+to type
+
+% make
+
+to compile all of the programs, and
+
+% make clean
+
+to remove all the files that were generated during compilation.
+
+There are also individual Makefiles for each separate example program.
+These makefiles have a ".mak" suffix. For example, Logging_Client.mak
+is the makefile for the Logging_Client program.
+
+All of the files in these directories are copyright Addison Wesley,
+and they come with absolutely no warranty whatsoever. Permission is
+hereby granted to use these programs for educational or commercial
+purposes.
diff --git a/ACE/examples/C++NPv1/RT_Thread_Per_Connection_Logging_Server.cpp b/ACE/examples/C++NPv1/RT_Thread_Per_Connection_Logging_Server.cpp
new file mode 100644
index 00000000000..febbf1964d5
--- /dev/null
+++ b/ACE/examples/C++NPv1/RT_Thread_Per_Connection_Logging_Server.cpp
@@ -0,0 +1,132 @@
+/*
+** $Id$
+**
+** Copyright 2001 Addison Wesley. All Rights Reserved.
+*/
+
+#include "ace/Auto_Ptr.h"
+#include "ace/FILE_IO.h"
+#include "ace/Log_Msg.h"
+#include "ace/Sched_Params.h"
+#include "ace/Signal.h"
+#include "ace/Thread_Manager.h"
+
+#include "RT_Thread_Per_Connection_Logging_Server.h"
+#include "Logging_Handler.h"
+
+#include <errno.h>
+
+namespace {
+ extern "C" void sigterm_handler (int /* signum */) { /* No-op. */ }
+}
+
+
+int
+RT_Thread_Per_Connection_Logging_Server::open (u_short port)
+{
+ ACE_Sched_Params fifo_sched_params
+ (ACE_SCHED_FIFO,
+ ACE_Sched_Params::priority_min (ACE_SCHED_FIFO),
+ ACE_SCOPE_PROCESS);
+
+ if (ACE_OS::sched_params (fifo_sched_params) != 0) {
+ if (errno == EPERM || errno == ENOTSUP)
+ ACE_DEBUG ((LM_DEBUG,
+ "Warning: user's not superuser, so "
+ "we're running in time-shared class\n"));
+ else
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%p\n", "ACE_OS::sched_params()"), -1);
+ }
+ // Initialize the parent classes.
+ return Thread_Per_Connection_Logging_Server::open (port);
+}
+
+
+int
+RT_Thread_Per_Connection_Logging_Server::handle_data (ACE_SOCK_Stream *client)
+{
+ int prio =
+ ACE_Sched_Params::next_priority
+ (ACE_SCHED_FIFO,
+ ACE_Sched_Params::priority_min (ACE_SCHED_FIFO),
+ ACE_SCOPE_THREAD);
+ ACE_OS::thr_setprio (prio);
+ return Thread_Per_Connection_Logging_Server::handle_data (client);
+}
+
+
+// For simplicity, the Thread_Per_Connection_Logging_Server methods
+// are duplicated here.
+
+ACE_THR_FUNC_RETURN Thread_Per_Connection_Logging_Server::run_svc (void *arg)
+{
+ auto_ptr<Thread_Args> thread_args (static_cast<Thread_Args *> (arg));
+
+ thread_args->this_->handle_data (&thread_args->logging_peer_);
+ thread_args->logging_peer_.close ();
+ return 0; // Return value is ignored
+}
+
+
+int
+Thread_Per_Connection_Logging_Server::handle_connections ()
+{
+ auto_ptr<Thread_Args> thread_args (new Thread_Args (this));
+
+ if (acceptor ().accept (thread_args->logging_peer_) == -1)
+ return -1;
+ if (ACE_Thread_Manager::instance ()->spawn (
+ // Pointer to function entry point.
+ Thread_Per_Connection_Logging_Server::run_svc,
+ // <run_svc> parameter.
+ static_cast<void *> (thread_args.get ()),
+ THR_DETACHED | THR_SCOPE_SYSTEM) == -1)
+ return -1;
+ thread_args.release (); // Spawned thread now owns memory
+ return 0;
+}
+
+
+int
+Thread_Per_Connection_Logging_Server::handle_data (ACE_SOCK_Stream *client)
+{
+ ACE_FILE_IO log_file;
+ // Client's hostname is logfile name.
+ make_log_file (log_file, client);
+
+ // Place the connection into blocking mode since this
+ // thread isn't doing anything except handling this client.
+ client->disable (ACE_NONBLOCK);
+
+ Logging_Handler logging_handler (log_file, *client);
+
+ // Keep handling log records until client closes connection
+ // or this thread is asked to cancel itself.
+ ACE_Thread_Manager *mgr = ACE_Thread_Manager::instance ();
+ ACE_thread_t me = ACE_Thread::self ();
+ while (!mgr->testcancel (me) &&
+ logging_handler.log_record () != -1)
+ continue;
+
+ log_file.close ();
+ return 0;
+}
+
+
+int main (int argc, char *argv[])
+{
+ // Register to receive the <SIGTERM> signal.
+ ACE_Sig_Action sa ((ACE_SignalHandler) sigterm_handler,
+ SIGTERM);
+
+ RT_Thread_Per_Connection_Logging_Server server;
+
+ if (server.run (argc, argv) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "server.run()"), 1);
+
+ // Cooperative thread cancellation and barrier synchronization.
+ ACE_Thread_Manager::instance ()->cancel_all ();
+ return ACE_Thread_Manager::instance ()->wait ();
+}
+
diff --git a/ACE/examples/C++NPv1/RT_Thread_Per_Connection_Logging_Server.h b/ACE/examples/C++NPv1/RT_Thread_Per_Connection_Logging_Server.h
new file mode 100644
index 00000000000..828a0e61a03
--- /dev/null
+++ b/ACE/examples/C++NPv1/RT_Thread_Per_Connection_Logging_Server.h
@@ -0,0 +1,22 @@
+/*
+** $Id$
+**
+** Copyright 2001 Addison Wesley. All Rights Reserved.
+*/
+
+#ifndef _RT_THREAD_PER_CONNECTION_LOGGING_SERVER_H
+#define _RT_THREAD_PER_CONNECTION_LOGGING_SERVER_H
+
+#include "ace/SOCK_Stream.h"
+#include "Logging_Server.h"
+#include "Thread_Per_Connection_Logging_Server.h"
+
+class RT_Thread_Per_Connection_Logging_Server :
+ public Thread_Per_Connection_Logging_Server
+{
+protected:
+ virtual int open (u_short port);
+ virtual int handle_data (ACE_SOCK_Stream * = 0);
+};
+
+#endif /* _RT_THREAD_PER_CONNECTION_LOGGING_SERVER_H */
diff --git a/ACE/examples/C++NPv1/Reactive_Logging_Server.cpp b/ACE/examples/C++NPv1/Reactive_Logging_Server.cpp
new file mode 100644
index 00000000000..39d2c6b51be
--- /dev/null
+++ b/ACE/examples/C++NPv1/Reactive_Logging_Server.cpp
@@ -0,0 +1,17 @@
+/*
+** $Id$
+**
+** Copyright 2001 Addison Wesley. All Rights Reserved.
+*/
+
+#include "ace/Log_Msg.h"
+#include "Reactive_Logging_Server.h"
+
+int main (int argc, char *argv[])
+{
+ Reactive_Logging_Server server;
+
+ if (server.run (argc, argv) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "server.run()"), 1);
+ return 0;
+}
diff --git a/ACE/examples/C++NPv1/Reactive_Logging_Server.h b/ACE/examples/C++NPv1/Reactive_Logging_Server.h
new file mode 100644
index 00000000000..482bcb32107
--- /dev/null
+++ b/ACE/examples/C++NPv1/Reactive_Logging_Server.h
@@ -0,0 +1,79 @@
+/*
+** $Id$
+**
+** Copyright 2001 Addison Wesley. All Rights Reserved.
+*/
+
+#ifndef _REACTIVE_LOGGING_SERVER_H
+#define _REACTIVE_LOGGING_SERVER_H
+
+#include "ace/INET_Addr.h"
+#include "ace/SOCK_Acceptor.h"
+#include "ace/SOCK_Stream.h"
+#include "ace/Log_Record.h"
+#include "ace/Handle_Set.h"
+#include "ace/os_include/os_fcntl.h"
+#include "Iterative_Logging_Server.h"
+
+class Reactive_Logging_Server : public Iterative_Logging_Server
+{
+protected:
+ // Keep track of the acceptor socket handle and all the
+ // connected stream socket handles.
+ ACE_Handle_Set master_handle_set_;
+
+ // Keep track of handles marked as active by <select>.
+ ACE_Handle_Set active_handles_;
+
+ virtual int open (u_short logger_port) {
+ Iterative_Logging_Server::open (logger_port);
+ master_handle_set_.set_bit (acceptor ().get_handle ());
+ acceptor ().enable (ACE_NONBLOCK);
+ return 0;
+ }
+
+ virtual int wait_for_multiple_events () {
+ active_handles_ = master_handle_set_;
+ int width = (int)active_handles_.max_set () + 1;
+ if (select (width,
+ active_handles_.fdset (),
+ 0, // no write_fds
+ 0, // no except_fds
+ 0) == -1) // no timeout
+ return -1;
+ active_handles_.sync
+ ((ACE_HANDLE) ((int) active_handles_.max_set () + 1));
+ return 0;
+ }
+
+ virtual int handle_connections () {
+ if (active_handles_.is_set (acceptor ().get_handle ())) {
+ while (acceptor ().accept (logging_handler ().peer ()) == 0)
+ master_handle_set_.set_bit
+ (logging_handler ().peer ().get_handle ());
+
+ // Remove acceptor handle from further consideration.
+ active_handles_.clr_bit (acceptor ().get_handle ());
+ }
+ return 0;
+ }
+
+ virtual int handle_data (ACE_SOCK_Stream *) {
+ ACE_Handle_Set_Iterator peer_iterator (active_handles_);
+
+ for (ACE_HANDLE handle;
+ (handle = peer_iterator ()) != ACE_INVALID_HANDLE;
+ ) {
+ logging_handler ().peer ().set_handle (handle);
+ if (logging_handler ().log_record () == -1) {
+ // Handle connection shutdown or comm failure.
+ master_handle_set_.clr_bit (handle);
+ logging_handler ().close ();
+ }
+ }
+ return 0;
+ }
+
+};
+
+#endif /* _REACTIVE_LOGGING_SERVER_H */
diff --git a/ACE/examples/C++NPv1/Reactive_Logging_Server_Ex.cpp b/ACE/examples/C++NPv1/Reactive_Logging_Server_Ex.cpp
new file mode 100644
index 00000000000..b8bc363180a
--- /dev/null
+++ b/ACE/examples/C++NPv1/Reactive_Logging_Server_Ex.cpp
@@ -0,0 +1,20 @@
+/*
+** $Id$
+**
+** Copyright 2001 Addison Wesley. All Rights Reserved.
+*/
+
+#include "ace/Functor.h"
+#include "ace/Log_Msg.h"
+
+#include "Reactive_Logging_Server_Ex.h"
+
+int main (int argc, char *argv[])
+{
+ Reactive_Logging_Server_Ex server;
+
+ if (server.run (argc, argv) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "server.run()"), 1);
+ return 0;
+}
+
diff --git a/ACE/examples/C++NPv1/Reactive_Logging_Server_Ex.h b/ACE/examples/C++NPv1/Reactive_Logging_Server_Ex.h
new file mode 100644
index 00000000000..c839b2453fc
--- /dev/null
+++ b/ACE/examples/C++NPv1/Reactive_Logging_Server_Ex.h
@@ -0,0 +1,95 @@
+/*
+** $Id$
+**
+** Copyright 2001 Addison Wesley. All Rights Reserved.
+*/
+
+#ifndef _REACTIVE_LOGGING_SERVER_EX_H
+#define _REACTIVE_LOGGING_SERVER_EX_H
+
+#include "ace/ACE.h"
+#include "ace/FILE_IO.h"
+#include "ace/Handle_Set.h"
+#include "ace/Hash_Map_Manager.h"
+#include "ace/INET_Addr.h"
+#include "ace/Log_Record.h"
+#include "ace/SOCK_Acceptor.h"
+#include "ace/SOCK_Stream.h"
+#include "Logging_Server.h"
+#include "Logging_Handler.h"
+#include "ace/Null_Mutex.h"
+#include "ace/os_include/os_fcntl.h"
+
+typedef ACE_Hash_Map_Manager<ACE_HANDLE,
+ ACE_FILE_IO *,
+ ACE_Null_Mutex> LOG_MAP;
+
+class Reactive_Logging_Server_Ex : public Logging_Server
+{
+protected:
+ // Associate an active handle to an <ACE_FILE_IO> pointer.
+ LOG_MAP log_map_;
+
+ // Keep track of acceptor socket and all the connected
+ // stream socket handles.
+ ACE_Handle_Set master_handle_set_;
+
+ // Keep track of read handles marked as active by <select>.
+ ACE_Handle_Set active_read_handles_;
+
+ virtual int open (u_short port) {
+ Logging_Server::open (port);
+ master_handle_set_.set_bit (acceptor ().get_handle ());
+ acceptor ().enable (ACE_NONBLOCK);
+ return 0;
+ }
+
+ virtual int wait_for_multiple_events () {
+ active_read_handles_ = master_handle_set_;
+ int width = (int) active_read_handles_.max_set () + 1;
+
+ return ACE::select (width, active_read_handles_);
+ }
+
+ virtual int handle_connections () {
+ ACE_SOCK_Stream logging_peer;
+
+ while (acceptor ().accept (logging_peer) != -1) {
+ ACE_FILE_IO *log_file = new ACE_FILE_IO;
+
+ // Use the client's hostname as the logfile name.
+ make_log_file (*log_file, &logging_peer);
+
+ // Add the new <logging_peer>'s handle to the map and
+ // to the set of handles we <select> for input.
+ log_map_.bind (logging_peer.get_handle (), log_file);
+ master_handle_set_.set_bit (logging_peer.get_handle ());
+ }
+ active_read_handles_.clr_bit (acceptor ().get_handle ());
+ return 0;
+ }
+
+ virtual int handle_data (ACE_SOCK_Stream *) {
+ ACE_Handle_Set_Iterator peer_iterator (active_read_handles_);
+
+ for (ACE_HANDLE handle;
+ (handle = peer_iterator ()) != ACE_INVALID_HANDLE;
+ ) {
+ ACE_FILE_IO *log_file = 0;
+ log_map_.find (handle, log_file);
+ Logging_Handler logging_handler (*log_file, handle);
+
+ if (logging_handler.log_record () == -1) {
+ logging_handler.close ();
+ master_handle_set_.clr_bit (handle);
+ log_map_.unbind (handle);
+ log_file->close ();
+ delete log_file;
+ }
+ }
+ return 0;
+ }
+
+};
+
+#endif /* _REACTIVE_LOGGING_SERVER_EX_H */
diff --git a/ACE/examples/C++NPv1/Thread_Per_Connection_Logging_Server.cpp b/ACE/examples/C++NPv1/Thread_Per_Connection_Logging_Server.cpp
new file mode 100644
index 00000000000..3737957ff70
--- /dev/null
+++ b/ACE/examples/C++NPv1/Thread_Per_Connection_Logging_Server.cpp
@@ -0,0 +1,93 @@
+/*
+** $Id$
+**
+** Copyright 2001 Addison Wesley. All Rights Reserved.
+*/
+
+#include "ace/Auto_Ptr.h"
+#include "ace/FILE_IO.h"
+#include "ace/Log_Msg.h"
+#include "ace/Signal.h"
+#include "ace/Thread_Manager.h"
+
+#include "Thread_Per_Connection_Logging_Server.h"
+#include "Logging_Handler.h"
+
+#include <errno.h>
+
+namespace {
+ extern "C" void sigterm_handler (int /* signum */) { /* No-op. */ }
+}
+
+
+ACE_THR_FUNC_RETURN Thread_Per_Connection_Logging_Server::run_svc (void *arg)
+{
+ auto_ptr<Thread_Args> thread_args (static_cast<Thread_Args *> (arg));
+
+ thread_args->this_->handle_data (&thread_args->logging_peer_);
+ thread_args->logging_peer_.close ();
+ return 0; // Return value is ignored
+}
+
+
+int
+Thread_Per_Connection_Logging_Server::handle_connections ()
+{
+ auto_ptr<Thread_Args> thread_args (new Thread_Args (this));
+
+ if (acceptor ().accept (thread_args->logging_peer_) == -1)
+ return -1;
+ if (ACE_Thread_Manager::instance ()->spawn (
+ // Pointer to function entry point.
+ Thread_Per_Connection_Logging_Server::run_svc,
+ // <run_svc> parameter.
+ static_cast<void *> (thread_args.get ()),
+ THR_DETACHED | THR_SCOPE_SYSTEM) == -1)
+ return -1;
+ thread_args.release (); // Spawned thread now owns memory
+ return 0;
+}
+
+
+int
+Thread_Per_Connection_Logging_Server::handle_data (ACE_SOCK_Stream *client)
+{
+ ACE_FILE_IO log_file;
+ // Client's hostname is logfile name.
+ make_log_file (log_file, client);
+
+ // Place the connection into blocking mode since this
+ // thread isn't doing anything except handling this client.
+ client->disable (ACE_NONBLOCK);
+
+ Logging_Handler logging_handler (log_file, *client);
+
+ // Keep handling log records until client closes connection
+ // or this thread is asked to cancel itself.
+ ACE_Thread_Manager *mgr = ACE_Thread_Manager::instance ();
+ ACE_thread_t me = ACE_Thread::self ();
+ while (!mgr->testcancel (me) &&
+ logging_handler.log_record () != -1)
+ continue;
+
+ log_file.close ();
+ return 0;
+}
+
+
+int main (int argc, char *argv[])
+{
+ // Register to receive the <SIGTERM> signal.
+ ACE_Sig_Action sa ((ACE_SignalHandler) sigterm_handler,
+ SIGTERM);
+
+ Thread_Per_Connection_Logging_Server server;
+
+ if (server.run (argc, argv) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "server.run()"), 1);
+
+ // Cooperative thread cancellation and barrier synchronization.
+ ACE_Thread_Manager::instance ()->cancel_all ();
+ return ACE_Thread_Manager::instance ()->wait ();
+}
+
diff --git a/ACE/examples/C++NPv1/Thread_Per_Connection_Logging_Server.h b/ACE/examples/C++NPv1/Thread_Per_Connection_Logging_Server.h
new file mode 100644
index 00000000000..edf3651cf46
--- /dev/null
+++ b/ACE/examples/C++NPv1/Thread_Per_Connection_Logging_Server.h
@@ -0,0 +1,49 @@
+/*
+** $Id$
+**
+** Copyright 2001 Addison Wesley. All Rights Reserved.
+*/
+
+#ifndef _THREAD_PER_CONNECTION_LOGGING_SERVER_H
+#define _THREAD_PER_CONNECTION_LOGGING_SERVER_H
+
+#include "ace/SOCK_Stream.h"
+#include "Logging_Server.h"
+
+class Thread_Per_Connection_Logging_Server : public Logging_Server
+{
+private:
+ struct Thread_Args {
+ Thread_Args (Thread_Per_Connection_Logging_Server *lsp) : this_ (lsp) {}
+
+ Thread_Per_Connection_Logging_Server *this_;
+ ACE_SOCK_Stream logging_peer_;
+ };
+
+ // Passed as a parameter to <ACE_Thread_Manager::spawn>.
+ static ACE_THR_FUNC_RETURN run_svc (void *arg);
+
+protected:
+ virtual int handle_connections ();
+ virtual int handle_data (ACE_SOCK_Stream * = 0);
+
+public:
+ // Template Method that runs logging server's event loop. Need to
+ // reimplement this here because the threads spawned from handle_connections
+ // call handle_data; therefore, this method must not.
+ virtual int run (int argc, char *argv[]) {
+ if (open (argc > 1 ? atoi (argv[1]) : 0) == -1)
+ return -1;
+
+ for (;;) {
+ if (wait_for_multiple_events () == -1)
+ return -1;
+ if (handle_connections () == -1)
+ return -1;
+ }
+
+ return 0;
+ }
+};
+
+#endif /* _THREAD_PER_CONNECTION_LOGGING_SERVER_H */
diff --git a/ACE/examples/C++NPv2/.cvsignore b/ACE/examples/C++NPv2/.cvsignore
new file mode 100644
index 00000000000..560cd9f1c78
--- /dev/null
+++ b/ACE/examples/C++NPv2/.cvsignore
@@ -0,0 +1,14 @@
+configurable_logging_server
+configurable_logging_server
+display_logfile
+display_logfile
+reactor_logging_server
+reactor_logging_server
+select_reactor_loggin_server
+select_reactor_loggin_server
+sr_configurable_logging_server
+sr_configurable_logging_server
+tp_reactor_logging_server
+tp_reactor_logging_server
+x
+x
diff --git a/ACE/examples/C++NPv2/AC_CLD_export.h b/ACE/examples/C++NPv2/AC_CLD_export.h
new file mode 100644
index 00000000000..0f2b35ca4c4
--- /dev/null
+++ b/ACE/examples/C++NPv2/AC_CLD_export.h
@@ -0,0 +1,54 @@
+
+// -*- C++ -*-
+// $Id$
+// Definition for Win32 Export directives.
+// This file is generated automatically by generate_export_file.pl AC_CLD
+// ------------------------------
+#ifndef AC_CLD_EXPORT_H
+#define AC_CLD_EXPORT_H
+
+#include "ace/config-all.h"
+
+#if defined (ACE_AS_STATIC_LIBS) && !defined (AC_CLD_HAS_DLL)
+# define AC_CLD_HAS_DLL 0
+#endif /* ACE_AS_STATIC_LIBS && ! AC_CLD_HAS_DLL */
+
+#if !defined (AC_CLD_HAS_DLL)
+# define AC_CLD_HAS_DLL 1
+#endif /* ! AC_CLD_HAS_DLL */
+
+#if defined (AC_CLD_HAS_DLL) && (AC_CLD_HAS_DLL == 1)
+# if defined (AC_CLD_BUILD_DLL)
+# define AC_CLD_Export ACE_Proper_Export_Flag
+# define AC_CLD_SINGLETON_DECLARATION(T) ACE_EXPORT_SINGLETON_DECLARATION (T)
+# define AC_CLD_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) ACE_EXPORT_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK)
+# else /* AC_CLD_BUILD_DLL */
+# define AC_CLD_Export ACE_Proper_Import_Flag
+# define AC_CLD_SINGLETON_DECLARATION(T) ACE_IMPORT_SINGLETON_DECLARATION (T)
+# define AC_CLD_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) ACE_IMPORT_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK)
+# endif /* AC_CLD_BUILD_DLL */
+#else /* AC_CLD_HAS_DLL == 1 */
+# define AC_CLD_Export
+# define AC_CLD_SINGLETON_DECLARATION(T)
+# define AC_CLD_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK)
+#endif /* AC_CLD_HAS_DLL == 1 */
+
+// Set AC_CLD_NTRACE = 0 to turn on library specific tracing even if
+// tracing is turned off for ACE.
+#if !defined (AC_CLD_NTRACE)
+# if (ACE_NTRACE == 1)
+# define AC_CLD_NTRACE 1
+# else /* (ACE_NTRACE == 1) */
+# define AC_CLD_NTRACE 0
+# endif /* (ACE_NTRACE == 1) */
+#endif /* !AC_CLD_NTRACE */
+
+#if (AC_CLD_NTRACE == 1)
+# define AC_CLD_TRACE(X)
+#else /* (AC_CLD_NTRACE == 1) */
+# define AC_CLD_TRACE(X) ACE_TRACE_IMPL(X)
+#endif /* (AC_CLD_NTRACE == 1) */
+
+#endif /* AC_CLD_EXPORT_H */
+
+// End of auto generated file.
diff --git a/ACE/examples/C++NPv2/AC_Client_Logging_Daemon.cpp b/ACE/examples/C++NPv2/AC_Client_Logging_Daemon.cpp
new file mode 100644
index 00000000000..759dcb44861
--- /dev/null
+++ b/ACE/examples/C++NPv2/AC_Client_Logging_Daemon.cpp
@@ -0,0 +1,426 @@
+/*
+** $Id$
+**
+** Copyright 2002 Addison Wesley. All Rights Reserved.
+*/
+
+#include "ace/OS_NS_string.h"
+#include "ace/OS_NS_unistd.h"
+#include "ace/OS_NS_sys_socket.h"
+#include "ace/OS_NS_sys_time.h"
+#include "ace/INET_Addr.h"
+#include "ace/SOCK_Acceptor.h"
+#include "ace/SOCK_Connector.h"
+#include "ace/SOCK_Stream.h"
+#include "ace/Acceptor.h"
+#include "ace/Connector.h"
+#include "ace/Get_Opt.h"
+#include "ace/Handle_Set.h"
+#include "ace/Log_Record.h"
+#include "ace/Message_Block.h"
+#include "ace/Reactor.h"
+#include "ace/Service_Object.h"
+#include "ace/Signal.h"
+#include "ace/Svc_Handler.h"
+#include "ace/Thread_Manager.h"
+#include "ace/os_include/os_netdb.h"
+#include "Logging_Handler.h"
+#include "AC_CLD_export.h"
+
+#include "AC_Client_Logging_Daemon.h"
+
+#include <openssl/ssl.h>
+
+
+class AC_CLD_Acceptor
+ : public ACE_Acceptor<AC_Input_Handler, ACE_SOCK_ACCEPTOR> {
+public:
+ // Constructor.
+ AC_CLD_Acceptor (AC_Output_Handler *handler = 0)
+ : output_handler_ (handler), input_handler_ (handler) {}
+
+protected:
+ typedef ACE_Acceptor<AC_Input_Handler, ACE_SOCK_ACCEPTOR>
+ PARENT;
+
+ // <ACE_Acceptor> factory method.
+ virtual int make_svc_handler (AC_Input_Handler *&sh);
+
+ // <ACE_Reactor> close hook method.
+ virtual int handle_close (ACE_HANDLE = ACE_INVALID_HANDLE,
+ ACE_Reactor_Mask = 0);
+
+ // Pointer to the output handler.
+ AC_Output_Handler *output_handler_;
+
+ // Single input handler.
+ AC_Input_Handler input_handler_;
+};
+
+class AC_CLD_Connector
+ : public ACE_Connector<AC_Output_Handler, ACE_SOCK_CONNECTOR> {
+public:
+ typedef ACE_Connector<AC_Output_Handler, ACE_SOCK_CONNECTOR>
+ PARENT;
+
+ // Constructor.
+ AC_CLD_Connector (AC_Output_Handler *handler = 0)
+ : handler_ (handler), ssl_ctx_ (0), ssl_ (0) {}
+
+ // Destructor frees the SSL resources.
+ virtual ~AC_CLD_Connector (void) {
+ SSL_free (ssl_);
+ SSL_CTX_free (ssl_ctx_);
+ }
+
+ // Initialize the Connector.
+ virtual int open (ACE_Reactor *r = ACE_Reactor::instance (),
+ int flags = 0);
+
+ // Re-establish a connection to the logging server.
+ int reconnect ();
+
+protected:
+ // Connection establishment and authentication hook method.
+ virtual int connect_svc_handler
+ (AC_Output_Handler *&svc_handler,
+ const ACE_SOCK_Connector::PEER_ADDR &remote_addr,
+ ACE_Time_Value *timeout,
+ const ACE_SOCK_Connector::PEER_ADDR &local_addr,
+ int reuse_addr, int flags, int perms);
+
+ virtual int connect_svc_handler
+ (AC_Output_Handler *&svc_handler,
+ AC_Output_Handler *&sh_copy,
+ const ACE_SOCK_Connector::PEER_ADDR &remote_addr,
+ ACE_Time_Value *timeout,
+ const ACE_SOCK_Connector::PEER_ADDR &local_addr,
+ int reuse_addr, int flags, int perms);
+
+ // Pointer to <AC_Output_Handler> we're connecting.
+ AC_Output_Handler *handler_;
+
+ // Address at which logging server listens for connections.
+ ACE_INET_Addr remote_addr_;
+
+ // The SSL "context" data structure.
+ SSL_CTX *ssl_ctx_;
+
+ // The SSL data structure corresponding to authenticated SSL
+ // connections.
+ SSL *ssl_;
+};
+
+class AC_Client_Logging_Daemon : public ACE_Service_Object {
+protected:
+ // Factory that passively connects the <AC_Input_Handler>.
+ AC_CLD_Acceptor acceptor_;
+
+ // Factory that actively connects the <AC_Output_Handler>.
+ AC_CLD_Connector connector_;
+
+ // The <AC_Output_Handler> connected by <AC_CLD_Connector>.
+ AC_Output_Handler output_handler_;
+
+public:
+ // Constructor.
+ AC_Client_Logging_Daemon ()
+ : acceptor_ (&output_handler_),
+ connector_ (&output_handler_) {}
+
+ // Service Configurator hook methods.
+ virtual int init (int argc, ACE_TCHAR *argv[]);
+ virtual int fini ();
+ //virtual int info (ACE_TCHAR **bufferp, size_t length = 0) const;
+ //virtual int suspend ();
+ //virtual int resume ();
+};
+
+/******************************************************/
+
+#if !defined (FLUSH_TIMEOUT)
+#define FLUSH_TIMEOUT 120 /* 120 seconds == 2 minutes. */
+#endif /* FLUSH_TIMEOUT */
+
+int AC_Output_Handler::open (void *connector) {
+ connector_ =
+ static_cast<AC_CLD_Connector *> (connector);
+ int bufsiz = ACE_DEFAULT_MAX_SOCKET_BUFSIZ;
+ peer ().set_option (SOL_SOCKET, SO_SNDBUF,
+ &bufsiz, sizeof bufsiz);
+ if (reactor ()->register_handler
+ (this, ACE_Event_Handler::READ_MASK) == -1)
+ return -1;
+ if (msg_queue ()->activate ()
+ == ACE_Message_Queue_Base::ACTIVATED) {
+ msg_queue ()->high_water_mark (QUEUE_MAX);
+ return activate (THR_SCOPE_SYSTEM);
+ } else return 0;
+}
+
+int AC_Output_Handler::put (ACE_Message_Block *mb,
+ ACE_Time_Value *timeout) {
+ int retval;
+ while ((retval = putq (mb, timeout)) == -1) {
+ if (msg_queue ()->state () != ACE_Message_Queue_Base::PULSED)
+ break;
+ }
+ return retval;
+}
+
+int AC_Output_Handler::handle_input (ACE_HANDLE h) {
+ peer ().close ();
+ reactor ()->remove_handler
+ (h, ACE_Event_Handler::READ_MASK
+ | ACE_Event_Handler::DONT_CALL);
+ msg_queue ()->pulse ();
+ return 0;
+}
+
+int AC_Output_Handler::svc () {
+ ACE_Message_Block *chunk[ACE_IOV_MAX];
+ size_t message_index = 0;
+ ACE_Time_Value time_of_last_send (ACE_OS::gettimeofday ());
+ ACE_Time_Value timeout;
+ ACE_Sig_Action no_sigpipe ((ACE_SignalHandler) SIG_IGN);
+ ACE_Sig_Action original_action;
+ no_sigpipe.register_action (SIGPIPE, &original_action);
+
+ for (;;) {
+ if (message_index == 0) {
+ timeout = ACE_OS::gettimeofday ();
+ timeout += FLUSH_TIMEOUT;
+ }
+ ACE_Message_Block *mblk = 0;
+ if (getq (mblk, &timeout) == -1) {
+ if (errno == ESHUTDOWN) {
+ if (connector_->reconnect () == -1) break;
+ continue;
+ } else if (errno != EWOULDBLOCK) break;
+ else if (message_index == 0) continue;
+ } else {
+ if (mblk->size () == 0
+ && mblk->msg_type () == ACE_Message_Block::MB_STOP)
+ { mblk->release (); break; }
+ chunk[message_index] = mblk;
+ ++message_index;
+ }
+ if (message_index >= ACE_IOV_MAX ||
+ (ACE_OS::gettimeofday () - time_of_last_send
+ >= ACE_Time_Value(FLUSH_TIMEOUT))) {
+ if (send (chunk, message_index) == -1) break;
+ time_of_last_send = ACE_OS::gettimeofday ();
+ }
+ }
+
+ if (message_index > 0) send (chunk, message_index);
+ no_sigpipe.restore_action (SIGPIPE, original_action);
+ return 0;
+}
+
+int AC_Output_Handler::send (ACE_Message_Block *chunk[], size_t &count) {
+ iovec iov[ACE_IOV_MAX];
+ size_t iov_size;
+ int result = 0;
+
+ for (iov_size = 0; iov_size < count; ++iov_size) {
+ iov[iov_size].iov_base = chunk[iov_size]->rd_ptr ();
+ iov[iov_size].iov_len = chunk[iov_size]->length ();
+ }
+ while (peer ().sendv_n (iov, iov_size) == -1)
+ if (connector_->reconnect () == -1) {
+ result = -1;
+ break;
+ }
+
+ while (iov_size > 0) {
+ chunk[--iov_size]->release (); chunk[iov_size] = 0;
+ }
+ count = iov_size;
+ return result;
+}
+
+/******************************************************/
+
+int AC_Input_Handler::open (void *) {
+ ACE_HANDLE handle = peer ().get_handle ();
+ if (reactor ()->register_handler
+ (handle, this, ACE_Event_Handler::READ_MASK) == -1)
+ return -1;
+ connected_clients_.set_bit (handle);
+ return 0;
+}
+
+int AC_Input_Handler::close (u_long) {
+ ACE_Message_Block *shutdown_message = 0;
+ ACE_NEW_RETURN
+ (shutdown_message,
+ ACE_Message_Block (0, ACE_Message_Block::MB_STOP), -1);
+ output_handler_->put (shutdown_message);
+
+ reactor ()->remove_handler
+ (connected_clients_, ACE_Event_Handler::READ_MASK);
+ return output_handler_->wait ();
+}
+
+int AC_Input_Handler::handle_input (ACE_HANDLE handle) {
+ ACE_Message_Block *mblk = 0;
+ Logging_Handler logging_handler (handle);
+
+ if (logging_handler.recv_log_record (mblk) != -1)
+ if (output_handler_->put (mblk->cont ()) != -1) {
+ mblk->cont (0);
+ mblk->release ();
+ return 0; // Success return.
+ } else mblk->release ();
+ return -1; // Error return.
+}
+
+int AC_Input_Handler::handle_close (ACE_HANDLE handle,
+ ACE_Reactor_Mask) {
+ connected_clients_.clr_bit (handle);
+ return ACE_OS::closesocket (handle);
+}
+
+/********************************************************/
+
+int AC_CLD_Acceptor::make_svc_handler (AC_Input_Handler *&sh)
+{ sh = &input_handler_; return 0; }
+
+
+int AC_CLD_Acceptor::handle_close (ACE_HANDLE,
+ ACE_Reactor_Mask) {
+ PARENT::handle_close ();
+ input_handler_.close ();
+ return 0;
+}
+
+/*******************************************************/
+
+#if !defined (CLD_CERTIFICATE_FILENAME)
+# define CLD_CERTIFICATE_FILENAME "cld-cert.pem"
+#endif /* !CLD_CERTIFICATE_FILENAME */
+#if !defined (CLD_KEY_FILENAME)
+# define CLD_KEY_FILENAME "cld-key.pem"
+#endif /* !CLD_KEY_FILENAME */
+
+int AC_CLD_Connector::open (ACE_Reactor *r, int flags) {
+ if (PARENT::open (r, flags) != 0) return -1;
+ OpenSSL_add_ssl_algorithms ();
+ ssl_ctx_ = SSL_CTX_new (SSLv3_client_method ());
+ if (ssl_ctx_ == 0) return -1;
+
+ if (SSL_CTX_use_certificate_file (ssl_ctx_,
+ CLD_CERTIFICATE_FILENAME,
+ SSL_FILETYPE_PEM) <= 0
+ || SSL_CTX_use_PrivateKey_file (ssl_ctx_,
+ CLD_KEY_FILENAME,
+ SSL_FILETYPE_PEM) <= 0
+ || !SSL_CTX_check_private_key (ssl_ctx_))
+ return -1;
+
+ ssl_ = SSL_new (ssl_ctx_);
+ if (ssl_ == 0) return -1;
+ return 0;
+}
+
+int AC_CLD_Connector::connect_svc_handler
+ (AC_Output_Handler *&svc_handler,
+ const ACE_SOCK_Connector::PEER_ADDR &remote_addr,
+ ACE_Time_Value *timeout,
+ const ACE_SOCK_Connector::PEER_ADDR &local_addr,
+ int reuse_addr, int flags, int perms) {
+ if (PARENT::connect_svc_handler
+ (svc_handler, remote_addr, timeout,
+ local_addr, reuse_addr, flags, perms) == -1) return -1;
+ SSL_clear (ssl_);
+#if defined (ACE_WIN32)
+ // ACE_WIN32 is the only platform where ACE_HANDLE is not an int.
+ // See ace/config-lite.h for the typedefs.
+ SSL_set_fd (ssl_,
+ reinterpret_cast<int> (svc_handler->get_handle ()));
+#else
+ SSL_set_fd (ssl_, svc_handler->get_handle ());
+#endif /* ACE_WIN32 */
+
+ SSL_set_verify (ssl_, SSL_VERIFY_PEER, 0);
+
+ if (SSL_connect (ssl_) == -1
+ || SSL_shutdown (ssl_) == -1) return -1;
+ remote_addr_ = remote_addr;
+ return 0;
+}
+
+int AC_CLD_Connector::connect_svc_handler
+ (AC_Output_Handler *&svc_handler,
+ AC_Output_Handler *&sh_copy,
+ const ACE_SOCK_Connector::PEER_ADDR &remote_addr,
+ ACE_Time_Value *timeout,
+ const ACE_SOCK_Connector::PEER_ADDR &local_addr,
+ int reuse_addr, int flags, int perms) {
+ sh_copy = svc_handler;
+ return this->connect_svc_handler (svc_handler, remote_addr, timeout,
+ local_addr, reuse_addr, flags, perms);
+}
+
+int AC_CLD_Connector::reconnect () {
+ // Maximum number of times to retry connect.
+ const size_t MAX_RETRIES = 5;
+ ACE_Time_Value timeout (1);
+ size_t i;
+ for (i = 0; i < MAX_RETRIES; ++i) {
+ ACE_Synch_Options options (ACE_Synch_Options::USE_TIMEOUT,
+ timeout);
+ if (i > 0) ACE_OS::sleep (timeout);
+ if (connect (handler_, remote_addr_, options) == 0)
+ break;
+ timeout *= 2; // Exponential backoff.
+ }
+ return i == MAX_RETRIES ? -1 : 0;
+}
+
+/******************************************************/
+
+int AC_Client_Logging_Daemon::init
+ (int argc, ACE_TCHAR *argv[]) {
+ u_short cld_port = ACE_DEFAULT_SERVICE_PORT;
+ u_short sld_port = ACE_DEFAULT_LOGGING_SERVER_PORT;
+ ACE_TCHAR sld_host[MAXHOSTNAMELEN];
+ ACE_OS::strcpy (sld_host, ACE_LOCALHOST);
+
+ ACE_Get_Opt get_opt (argc, argv, ACE_TEXT ("p:r:s:"), 0);
+ get_opt.long_option (ACE_TEXT ("client_port"), 'p',
+ ACE_Get_Opt::ARG_REQUIRED);
+ get_opt.long_option (ACE_TEXT ("server_port"), 'r',
+ ACE_Get_Opt::ARG_REQUIRED);
+ get_opt.long_option (ACE_TEXT ("server_name"), 's',
+ ACE_Get_Opt::ARG_REQUIRED);
+
+ for (int c; (c = get_opt ()) != -1;)
+ switch (c) {
+ case 'p': // Client logging daemon acceptor port number.
+ cld_port = static_cast<u_short> (ACE_OS::atoi (get_opt.opt_arg ()));
+ break;
+ case 'r': // Server logging daemon acceptor port number.
+ sld_port = static_cast<u_short> (ACE_OS::atoi (get_opt.opt_arg ()));
+ break;
+ case 's': // Server logging daemon hostname.
+ ACE_OS::strsncpy
+ (sld_host, get_opt.opt_arg (), MAXHOSTNAMELEN);
+ break;
+ }
+
+ ACE_INET_Addr cld_addr (cld_port);
+ ACE_INET_Addr sld_addr (sld_port, sld_host);
+
+ if (acceptor_.open (cld_addr) == -1) return -1;
+ AC_Output_Handler *oh = &output_handler_;
+ if (connector_.connect (oh, sld_addr) == -1)
+ { acceptor_.close (); return -1; }
+ return 0;
+}
+
+int AC_Client_Logging_Daemon::fini ()
+{ return acceptor_.close (); }
+
+ACE_FACTORY_DEFINE (AC_CLD, AC_Client_Logging_Daemon)
diff --git a/ACE/examples/C++NPv2/AC_Client_Logging_Daemon.h b/ACE/examples/C++NPv2/AC_Client_Logging_Daemon.h
new file mode 100644
index 00000000000..20f3581f623
--- /dev/null
+++ b/ACE/examples/C++NPv2/AC_Client_Logging_Daemon.h
@@ -0,0 +1,62 @@
+/*
+** $Id$
+**
+** Copyright 2002 Addison Wesley. All Rights Reserved.
+*/
+
+#ifndef _AC_CLIENT_LOGGING_DAEMON_H
+#define _AC_CLIENT_LOGGING_DAEMON_H
+
+#include "ace/Handle_Set.h"
+#include "ace/Log_Record.h"
+#include "ace/SOCK_Stream.h"
+#include "ace/Svc_Handler.h"
+#include "ace/Synch_Traits.h"
+
+class AC_CLD_Connector;
+
+class AC_Output_Handler
+ : public ACE_Svc_Handler<ACE_SOCK_STREAM, ACE_MT_SYNCH> {
+public:
+ enum { QUEUE_MAX = sizeof (ACE_Log_Record) * ACE_IOV_MAX };
+
+ virtual int open (void *); // Initialization hook method.
+
+ // Entry point into the <AC_Output_Handler>.
+ virtual int put (ACE_Message_Block *, ACE_Time_Value * = 0);
+
+protected:
+ AC_CLD_Connector *connector_;
+
+ // Handle disconnects from the logging server.
+ virtual int handle_input (ACE_HANDLE handle);
+
+ // Hook method forwards log records to server logging daemon.
+ virtual int svc ();
+
+ // Send the buffered log records using a gather-write operation.
+ virtual int send (ACE_Message_Block *chunk[], size_t &count);
+};
+
+class AC_Input_Handler
+ : public ACE_Svc_Handler<ACE_SOCK_STREAM, ACE_NULL_SYNCH> {
+public:
+ AC_Input_Handler (AC_Output_Handler *handler = 0)
+ : output_handler_ (handler) {}
+ virtual int open (void *); // Initialization hook method.
+ virtual int close (u_long = 0); // Shutdown hook method.
+
+protected:
+ // Reactor hook methods.
+ virtual int handle_input (ACE_HANDLE handle);
+ virtual int handle_close (ACE_HANDLE = ACE_INVALID_HANDLE,
+ ACE_Reactor_Mask = 0);
+
+ // Pointer to the output handler.
+ AC_Output_Handler *output_handler_;
+
+ // Keep track of connected client handles.
+ ACE_Handle_Set connected_clients_;
+};
+
+#endif /* _AC_CLIENT_LOGGING_DAEMON_H */
diff --git a/ACE/examples/C++NPv2/AIO_CLD_export.h b/ACE/examples/C++NPv2/AIO_CLD_export.h
new file mode 100644
index 00000000000..315bc287cf3
--- /dev/null
+++ b/ACE/examples/C++NPv2/AIO_CLD_export.h
@@ -0,0 +1,54 @@
+
+// -*- C++ -*-
+// $Id$
+// Definition for Win32 Export directives.
+// This file is generated automatically by generate_export_file.pl AIO_CLD
+// ------------------------------
+#ifndef AIO_CLD_EXPORT_H
+#define AIO_CLD_EXPORT_H
+
+#include "ace/config-all.h"
+
+#if defined (ACE_AS_STATIC_LIBS) && !defined (AIO_CLD_HAS_DLL)
+# define AIO_CLD_HAS_DLL 0
+#endif /* ACE_AS_STATIC_LIBS && ! AIO_CLD_HAS_DLL */
+
+#if !defined (AIO_CLD_HAS_DLL)
+# define AIO_CLD_HAS_DLL 1
+#endif /* ! AIO_CLD_HAS_DLL */
+
+#if defined (AIO_CLD_HAS_DLL) && (AIO_CLD_HAS_DLL == 1)
+# if defined (AIO_CLD_BUILD_DLL)
+# define AIO_CLD_Export ACE_Proper_Export_Flag
+# define AIO_CLD_SINGLETON_DECLARATION(T) ACE_EXPORT_SINGLETON_DECLARATION (T)
+# define AIO_CLD_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) ACE_EXPORT_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK)
+# else /* AIO_CLD_BUILD_DLL */
+# define AIO_CLD_Export ACE_Proper_Import_Flag
+# define AIO_CLD_SINGLETON_DECLARATION(T) ACE_IMPORT_SINGLETON_DECLARATION (T)
+# define AIO_CLD_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) ACE_IMPORT_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK)
+# endif /* AIO_CLD_BUILD_DLL */
+#else /* AIO_CLD_HAS_DLL == 1 */
+# define AIO_CLD_Export
+# define AIO_CLD_SINGLETON_DECLARATION(T)
+# define AIO_CLD_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK)
+#endif /* AIO_CLD_HAS_DLL == 1 */
+
+// Set AIO_CLD_NTRACE = 0 to turn on library specific tracing even if
+// tracing is turned off for ACE.
+#if !defined (AIO_CLD_NTRACE)
+# if (ACE_NTRACE == 1)
+# define AIO_CLD_NTRACE 1
+# else /* (ACE_NTRACE == 1) */
+# define AIO_CLD_NTRACE 0
+# endif /* (ACE_NTRACE == 1) */
+#endif /* !AIO_CLD_NTRACE */
+
+#if (AIO_CLD_NTRACE == 1)
+# define AIO_CLD_TRACE(X)
+#else /* (AIO_CLD_NTRACE == 1) */
+# define AIO_CLD_TRACE(X) ACE_TRACE_IMPL(X)
+#endif /* (AIO_CLD_NTRACE == 1) */
+
+#endif /* AIO_CLD_EXPORT_H */
+
+// End of auto generated file.
diff --git a/ACE/examples/C++NPv2/AIO_Client_Logging_Daemon.cpp b/ACE/examples/C++NPv2/AIO_Client_Logging_Daemon.cpp
new file mode 100644
index 00000000000..56983e8f89a
--- /dev/null
+++ b/ACE/examples/C++NPv2/AIO_Client_Logging_Daemon.cpp
@@ -0,0 +1,360 @@
+/*
+** $Id$
+**
+** Copyright 2002 Addison Wesley. All Rights Reserved.
+*/
+
+#include "ace/config-all.h"
+
+#if (defined (ACE_WIN32) && !defined (ACE_HAS_WINCE)) || (defined (ACE_HAS_AIO_CALLS))
+
+#include "ace/OS_NS_string.h"
+#include "ace/OS_NS_sys_socket.h"
+#include "ace/Asynch_Acceptor.h"
+#include "ace/Asynch_Connector.h"
+#include "ace/Asynch_IO.h"
+#include "ace/CDR_Stream.h"
+#include "ace/Get_Opt.h"
+#include "ace/INET_Addr.h"
+#include "ace/Message_Block.h"
+#include "ace/Null_Condition.h"
+#include "ace/Null_Mutex.h"
+#include "ace/Proactor.h"
+#include "ace/SOCK_Stream.h"
+#include "ace/Service_Object.h"
+#include "ace/Signal.h"
+#include "ace/Singleton.h"
+#include "ace/Task.h"
+#include "ace/Thread_Manager.h"
+#include "ace/Unbounded_Set.h"
+#include "ace/os_include/os_netdb.h"
+#include "AIO_CLD_export.h"
+#include "AIO_Client_Logging_Daemon.h"
+#include <openssl/ssl.h>
+
+
+
+class AIO_CLD_Acceptor
+ : public ACE_Asynch_Acceptor<AIO_Input_Handler> {
+public:
+ // Cancel accept and close all clients.
+ void close (void);
+
+ // Remove handler from client set.
+ void remove (AIO_Input_Handler *ih)
+ { clients_.remove (ih); }
+
+protected:
+ // Service handler factory method.
+ virtual AIO_Input_Handler *make_handler (void);
+
+ // Set of all connected clients
+ ACE_Unbounded_Set<AIO_Input_Handler *> clients_;
+};
+
+
+class AIO_Client_Logging_Daemon : public ACE_Task<ACE_NULL_SYNCH> {
+protected:
+ ACE_INET_Addr cld_addr_;
+ ACE_INET_Addr sld_addr_;
+
+ // Factory that passively connects the <AIO_Input_Handler>.
+ AIO_CLD_Acceptor acceptor_;
+
+public:
+ // Service Configurator hook methods.
+ virtual int init (int argc, ACE_TCHAR *argv[]);
+ virtual int fini ();
+ virtual int svc (void);
+};
+
+/******************************************************/
+
+AIO_Output_Handler::~AIO_Output_Handler () {
+ reader_.cancel ();
+ writer_.cancel ();
+ ACE_OS::closesocket (handle ());
+}
+
+int AIO_Output_Handler::put (ACE_Message_Block *mb,
+ ACE_Time_Value *timeout) {
+ if (can_write_) { start_write (mb); return 0; }
+ return putq (mb, timeout);
+}
+
+void AIO_Output_Handler::open
+ (ACE_HANDLE new_handle, ACE_Message_Block &) {
+ ACE_SOCK_Stream peer (new_handle);
+ int bufsiz = ACE_DEFAULT_MAX_SOCKET_BUFSIZ;
+ peer.set_option (SOL_SOCKET, SO_SNDBUF,
+ &bufsiz, sizeof bufsiz);
+
+ reader_.open (*this, new_handle, 0, proactor ());
+ writer_.open (*this, new_handle, 0, proactor ());
+
+ ACE_Message_Block *mb;
+ ACE_NEW (mb, ACE_Message_Block (1));
+ reader_.read (*mb, 1);
+ ACE_Sig_Action no_sigpipe ((ACE_SignalHandler) SIG_IGN);
+ no_sigpipe.register_action (SIGPIPE, 0);
+ can_write_ = 1;
+ start_write (0);
+}
+
+void AIO_Output_Handler::start_write (ACE_Message_Block *mblk) {
+ if (mblk == 0) {
+ ACE_Time_Value nonblock (0);
+ getq (mblk, &nonblock);
+ }
+ if (mblk != 0) {
+ can_write_ = 0;
+ if (writer_.write (*mblk, mblk->length ()) == -1)
+ ungetq (mblk);
+ }
+}
+
+void AIO_Output_Handler::handle_read_stream
+ (const ACE_Asynch_Read_Stream::Result &result) {
+ result.message_block ().release ();
+ writer_.cancel ();
+ ACE_OS::closesocket (result.handle ());
+ handle (ACE_INVALID_HANDLE);
+ can_write_ = 0;
+ CLD_CONNECTOR::instance ()->reconnect ();
+}
+
+void AIO_Output_Handler::handle_write_stream
+ (const ACE_Asynch_Write_Stream::Result &result) {
+ ACE_Message_Block &mblk = result.message_block ();
+ if (!result.success ()) {
+ mblk.rd_ptr (mblk.base ());
+ ungetq (&mblk);
+ }
+ else {
+ can_write_ = handle () == result.handle ();
+ if (mblk.length () == 0) {
+ mblk.release ();
+ if (can_write_) start_write ();
+ }
+ else if (can_write_) start_write (&mblk);
+ else { mblk.rd_ptr (mblk.base ()); ungetq (&mblk); }
+ }
+}
+
+/******************************************************/
+
+AIO_Input_Handler::~AIO_Input_Handler () {
+ reader_.cancel ();
+ ACE_OS::closesocket (handle ());
+ if (mblk_ != 0) mblk_->release ();
+ mblk_ = 0;
+ acceptor_->remove (this);
+}
+
+void AIO_Input_Handler::open
+ (ACE_HANDLE new_handle, ACE_Message_Block &) {
+ reader_.open (*this, new_handle, 0, proactor ());
+ ACE_NEW_NORETURN
+ (mblk_, ACE_Message_Block (ACE_DEFAULT_CDR_BUFSIZE));
+ // Align the Message Block for a CDR stream
+ ACE_CDR::mb_align (mblk_);
+ reader_.read (*mblk_, LOG_HEADER_SIZE);
+}
+
+void AIO_Input_Handler::handle_read_stream
+ (const ACE_Asynch_Read_Stream::Result &result) {
+ if (!result.success () || result.bytes_transferred () == 0)
+ delete this;
+ else if (result.bytes_transferred () < result.bytes_to_read ())
+ reader_.read (*mblk_, result.bytes_to_read () -
+ result.bytes_transferred ());
+ else if (mblk_->length () == LOG_HEADER_SIZE) {
+ ACE_InputCDR cdr (mblk_);
+
+ ACE_CDR::Boolean byte_order;
+ cdr >> ACE_InputCDR::to_boolean (byte_order);
+ cdr.reset_byte_order (byte_order);
+
+ ACE_CDR::ULong length;
+ cdr >> length;
+
+ mblk_->size (length + LOG_HEADER_SIZE);
+ reader_.read (*mblk_, length);
+ }
+ else {
+ if (OUTPUT_HANDLER::instance ()->put (mblk_) == -1)
+ mblk_->release ();
+
+ ACE_NEW_NORETURN
+ (mblk_, ACE_Message_Block (ACE_DEFAULT_CDR_BUFSIZE));
+ ACE_CDR::mb_align (mblk_);
+ reader_.read (*mblk_, LOG_HEADER_SIZE);
+ }
+}
+
+/********************************************************/
+
+void AIO_CLD_Acceptor::close (void) {
+ ACE_Unbounded_Set_Iterator<AIO_Input_Handler *>
+ iter (clients_.begin ());
+ AIO_Input_Handler **ih;
+ while (iter.next (ih))
+ delete *ih;
+}
+
+AIO_Input_Handler * AIO_CLD_Acceptor::make_handler (void) {
+ AIO_Input_Handler *ih;
+ ACE_NEW_RETURN (ih, AIO_Input_Handler (this), 0);
+ if (clients_.insert (ih) == -1)
+ { delete ih; return 0; }
+ return ih;
+}
+
+/*******************************************************/
+
+#if !defined (CLD_CERTIFICATE_FILENAME)
+# define CLD_CERTIFICATE_FILENAME "cld-cert.pem"
+#endif /* !CLD_CERTIFICATE_FILENAME */
+#if !defined (CLD_KEY_FILENAME)
+# define CLD_KEY_FILENAME "cld-key.pem"
+#endif /* !CLD_KEY_FILENAME */
+
+
+int AIO_CLD_Connector::validate_connection
+ (const ACE_Asynch_Connect::Result& result,
+ const ACE_INET_Addr &remote, const ACE_INET_Addr&) {
+
+ remote_addr_ = remote;
+ if (!result.success ()) {
+ ACE_Time_Value delay (retry_delay_);
+ retry_delay_ *= 2;
+ if (retry_delay_ > MAX_RETRY_DELAY)
+ retry_delay_ = MAX_RETRY_DELAY;
+ proactor ()->schedule_timer (*this, 0, delay);
+ return -1;
+ }
+ retry_delay_ = INITIAL_RETRY_DELAY;
+
+ if (ssl_ctx_ == 0) {
+ OpenSSL_add_ssl_algorithms ();
+ ssl_ctx_ = SSL_CTX_new (SSLv3_client_method ());
+ if (ssl_ctx_ == 0) return -1;
+
+ if (SSL_CTX_use_certificate_file (ssl_ctx_,
+ CLD_CERTIFICATE_FILENAME,
+ SSL_FILETYPE_PEM) <= 0
+ || SSL_CTX_use_PrivateKey_file (ssl_ctx_,
+ CLD_KEY_FILENAME,
+ SSL_FILETYPE_PEM) <= 0
+ || !SSL_CTX_check_private_key (ssl_ctx_)) {
+ SSL_CTX_free (ssl_ctx_);
+ ssl_ctx_ = 0;
+ return -1;
+ }
+ ssl_ = SSL_new (ssl_ctx_);
+ if (ssl_ == 0) {
+ SSL_CTX_free (ssl_ctx_); ssl_ctx_ = 0;
+ return -1;
+ }
+ }
+
+ SSL_clear (ssl_);
+#if defined (ACE_WIN32)
+ // ACE_WIN32 is the only platform where ACE_HANDLE is not an int.
+ // See ace/config-lite.h for the typedefs.
+ SSL_set_fd (ssl_, reinterpret_cast<int> (result.connect_handle ()));
+#else
+ SSL_set_fd (ssl_, result.connect_handle ());
+#endif /* ACE_WIN32 */
+ SSL_set_verify (ssl_, SSL_VERIFY_PEER, 0);
+
+ if (SSL_connect (ssl_) == -1
+ || SSL_shutdown (ssl_) == -1) return -1;
+ return 0;
+}
+
+void AIO_CLD_Connector::handle_time_out
+(const ACE_Time_Value&, const void *) {
+ connect (remote_addr_);
+}
+
+/******************************************************/
+
+int AIO_Client_Logging_Daemon::init
+ (int argc, ACE_TCHAR *argv[]) {
+ u_short cld_port = ACE_DEFAULT_SERVICE_PORT;
+ u_short sld_port = ACE_DEFAULT_LOGGING_SERVER_PORT;
+ ACE_TCHAR sld_host[MAXHOSTNAMELEN];
+ ACE_OS::strcpy (sld_host, ACE_LOCALHOST);
+
+ ACE_Get_Opt get_opt (argc, argv, ACE_TEXT ("p:r:s:"), 0);
+ get_opt.long_option (ACE_TEXT ("client_port"), 'p',
+ ACE_Get_Opt::ARG_REQUIRED);
+ get_opt.long_option (ACE_TEXT ("server_port"), 'r',
+ ACE_Get_Opt::ARG_REQUIRED);
+ get_opt.long_option (ACE_TEXT ("server_name"), 's',
+ ACE_Get_Opt::ARG_REQUIRED);
+
+ for (int c; (c = get_opt ()) != -1;)
+ switch (c) {
+ case 'p': // Client logging daemon acceptor port number.
+ cld_port = static_cast<u_short> (ACE_OS::atoi (get_opt.opt_arg ()));
+ break;
+ case 'r': // Server logging daemon acceptor port number.
+ sld_port = static_cast<u_short> (ACE_OS::atoi (get_opt.opt_arg ()));
+ break;
+ case 's': // Server logging daemon hostname.
+ ACE_OS::strsncpy
+ (sld_host, get_opt.opt_arg (), MAXHOSTNAMELEN);
+ break;
+ }
+
+ if (cld_addr_.set (cld_port) == -1 ||
+ sld_addr_.set (sld_port, sld_host) == -1)
+ return -1;
+ return activate ();
+}
+
+int AIO_Client_Logging_Daemon::fini () {
+ ACE_Proactor::instance ()->proactor_end_event_loop ();
+ wait ();
+ return 0;
+}
+
+int AIO_Client_Logging_Daemon::svc (void) {
+ if (acceptor_.open (cld_addr_) == -1) return -1;
+ if (CLD_CONNECTOR::instance ()->connect (sld_addr_) == 0)
+ ACE_Proactor::instance ()->proactor_run_event_loop ();
+ acceptor_.close ();
+ CLD_CONNECTOR::close ();
+ OUTPUT_HANDLER::close ();
+ return 0;
+}
+
+#else /* There's no AIO support on this platform */
+
+#include "ace/Task.h"
+#include "ace/Service_Object.h"
+#include "ace/Synch_Traits.h"
+#include "AIO_CLD_export.h"
+
+class AIO_Client_Logging_Daemon : public ACE_Task<ACE_NULL_SYNCH> {
+public:
+ // Service Configurator hook methods.
+ virtual int init (int, ACE_TCHAR *[]);
+ virtual int fini ();
+};
+
+int AIO_Client_Logging_Daemon::init (int, ACE_TCHAR *[]) {
+
+ ACE_ERROR_RETURN
+ ((LM_ERROR, ACE_TEXT ("This service requires AIO support\n")), -1);
+}
+
+int AIO_Client_Logging_Daemon::fini () {
+ return 0;
+}
+
+ACE_FACTORY_DEFINE (AIO_CLD, AIO_Client_Logging_Daemon)
+
+#endif /* (ACE_WIN32 && !ACE_HAS_WINCE) || ACE_HAS_AIO_CALLS */
diff --git a/ACE/examples/C++NPv2/AIO_Client_Logging_Daemon.h b/ACE/examples/C++NPv2/AIO_Client_Logging_Daemon.h
new file mode 100644
index 00000000000..7c0d81da606
--- /dev/null
+++ b/ACE/examples/C++NPv2/AIO_Client_Logging_Daemon.h
@@ -0,0 +1,135 @@
+/*
+** $Id$
+**
+** Copyright 2002 Addison Wesley. All Rights Reserved.
+*/
+
+#ifndef _AIO_CLIENT_LOGGING_DAEMON_H
+#define _AIO_CLIENT_LOGGING_DAEMON_H
+
+#include "ace/Asynch_Connector.h"
+#include "ace/Asynch_IO.h"
+#include "ace/Message_Block.h"
+#include "ace/Null_Mutex.h"
+#include "ace/Proactor.h"
+#include "ace/Singleton.h"
+#include "ace/Synch_Traits.h"
+#include "ace/Task.h"
+
+#include <openssl/ssl.h>
+
+class AIO_CLD_Acceptor;
+
+class AIO_Input_Handler : public ACE_Service_Handler {
+public:
+ AIO_Input_Handler (AIO_CLD_Acceptor *acc = 0)
+ : acceptor_ (acc), mblk_ (0) {}
+
+ virtual ~AIO_Input_Handler ();
+
+ // Called by ACE_Asynch_Acceptor when a client connects.
+ virtual void open (ACE_HANDLE new_handle,
+ ACE_Message_Block &message_block);
+
+protected:
+ enum { LOG_HEADER_SIZE = 8 }; // Length of CDR header
+ AIO_CLD_Acceptor *acceptor_; // Our creator
+ ACE_Message_Block *mblk_; // Block to receive log record
+ ACE_Asynch_Read_Stream reader_; // Async read factory
+
+ // Handle input from logging clients.
+ virtual void handle_read_stream
+ (const ACE_Asynch_Read_Stream::Result &result);
+};
+
+
+class AIO_Output_Handler
+ : public ACE_Task<ACE_NULL_SYNCH>,
+ public ACE_Service_Handler {
+public:
+ AIO_Output_Handler () : can_write_ (0) {}
+
+ virtual ~AIO_Output_Handler ();
+
+ // Entry point into the <AIO_Output_Handler>.
+ virtual int put (ACE_Message_Block *, ACE_Time_Value * = 0);
+
+ // Hook method called when server connection is established.
+ using ACE_Service_Handler::open;
+ virtual void open (ACE_HANDLE new_handle,
+ ACE_Message_Block &message_block);
+
+protected:
+ ACE_Asynch_Read_Stream reader_; // Detects connection loss
+ ACE_Asynch_Write_Stream writer_; // Sends to server
+ int can_write_; // Safe to begin send a log record?
+
+ // Initiate the send of a log record
+ void start_write (ACE_Message_Block *mblk = 0);
+
+ // Handle disconnects from the logging server.
+ virtual void handle_read_stream
+ (const ACE_Asynch_Read_Stream::Result &result);
+
+ // Handle completed write to logging server.
+ virtual void handle_write_stream
+ (const ACE_Asynch_Write_Stream::Result &result);
+};
+
+typedef ACE_Unmanaged_Singleton<AIO_Output_Handler, ACE_Null_Mutex>
+ OUTPUT_HANDLER;
+
+
+class AIO_CLD_Connector
+ : public ACE_Asynch_Connector<AIO_Output_Handler> {
+public:
+ enum { INITIAL_RETRY_DELAY = 3, MAX_RETRY_DELAY = 60 };
+
+ // Constructor.
+ AIO_CLD_Connector ()
+ : retry_delay_ (INITIAL_RETRY_DELAY), ssl_ctx_ (0), ssl_ (0)
+ { open (); }
+
+ // Destructor frees the SSL resources.
+ virtual ~AIO_CLD_Connector (void) {
+ SSL_free (ssl_);
+ SSL_CTX_free (ssl_ctx_);
+ proactor ()->cancel_timer (*this);
+ }
+
+ // Hook method to detect failure and validate peer before
+ // opening handler.
+ virtual int validate_connection
+ (const ACE_Asynch_Connect::Result& result,
+ const ACE_INET_Addr &remote, const ACE_INET_Addr& local);
+
+ // Re-establish a connection to the logging server.
+ int reconnect (void) { return connect (remote_addr_); }
+
+protected:
+ // Hook method called on timer expiration - retry connect
+ virtual void handle_time_out
+ (const ACE_Time_Value&, const void *);
+
+ // Template method to create a new handler
+ virtual AIO_Output_Handler *make_handler (void)
+ { return OUTPUT_HANDLER::instance (); }
+
+ // Address at which logging server listens for connections.
+ ACE_INET_Addr remote_addr_;
+
+ // Seconds to wait before trying the next connect
+ int retry_delay_;
+
+ // The SSL "context" data structure.
+ SSL_CTX *ssl_ctx_;
+
+ // The SSL data structure corresponding to authenticated SSL
+ // connections.
+ SSL *ssl_;
+};
+
+typedef ACE_Unmanaged_Singleton<AIO_CLD_Connector, ACE_Null_Mutex>
+ CLD_CONNECTOR;
+
+#endif /* _AIO_CLIENT_LOGGING_DAEMON_H */
diff --git a/ACE/examples/C++NPv2/C++NPv2.mpc b/ACE/examples/C++NPv2/C++NPv2.mpc
new file mode 100644
index 00000000000..675db6f9929
--- /dev/null
+++ b/ACE/examples/C++NPv2/C++NPv2.mpc
@@ -0,0 +1,183 @@
+// -*- MPC -*-
+// $Id$
+
+// The specific section for gnuace is here to avoid problems
+// with parallel builds. Since the libraries in question share source
+// files, we need to ensure that one of them is built before all others.
+// Also, a specific section was used because you can't set build order
+// without setting a build dependency within vc6 and the like.
+
+project(*AC_CLD) : acelib, ssl {
+ avoids += uses_wchar
+ sharedname = AC_CLD
+ dynamicflags = AC_CLD_BUILD_DLL
+ specific(gnuace) {
+ after += *CLD
+ }
+ Source_Files {
+ AC_Client_Logging_Daemon.cpp
+ Logging_Handler.cpp
+ }
+}
+
+project(*AIO_CLD) : acelib, ssl {
+ sharedname = AIO_CLD
+ dynamicflags = AIO_CLD_BUILD_DLL
+ Source_Files {
+ AIO_Client_Logging_Daemon.cpp
+ }
+}
+
+project(*CLD) : acelib {
+ avoids += uses_wchar ace_for_tao
+ sharedname = CLD
+ dynamicflags = CLD_BUILD_DLL
+ Source_Files {
+ Client_Logging_Daemon.cpp
+ Logging_Acceptor.cpp
+ Logging_Event_Handler.cpp
+ Logging_Handler.cpp
+ }
+}
+
+project(*Configurable_Log_Server) : aceexe {
+ avoids += uses_wchar
+ exename = configurable_logging_server
+ Source_Files {
+ Configurable_Logging_Server.cpp
+ Service_Reporter.cpp
+ }
+}
+
+project(*Display_Logfile) : aceexe {
+ avoids += ace_for_tao
+ exename = display_logfile
+ Source_Files {
+ display_logfile.cpp
+ }
+}
+
+project(*Reactor_Log_Server) : aceexe {
+ avoids += uses_wchar ace_for_tao
+ exename = reactor_logging_server
+ Source_Files {
+ Logging_Acceptor.cpp
+ Logging_Event_Handler.cpp
+ Logging_Event_Handler_Ex.cpp
+ Logging_Handler.cpp
+ Reactor_Logging_Server.cpp
+ }
+}
+
+project(*Select_Reactor_Log_Server) : aceexe {
+ avoids += uses_wchar ace_for_tao
+ exename = select_reactor_logging_server
+ specific(gnuace) {
+ after += *Reactor_Log_Server
+ }
+ Source_Files {
+ Logging_Acceptor.cpp
+ Logging_Event_Handler.cpp
+ Logging_Event_Handler_Ex.cpp
+ Logging_Handler.cpp
+ Select_Reactor_Logging_Server.cpp
+ }
+}
+
+project(*SLD) : acelib {
+ avoids += uses_wchar ace_for_tao
+ sharedname = SLD
+ dynamicflags = SLD_BUILD_DLL
+ specific(gnuace) {
+ after += *CLD
+ }
+ Source_Files {
+ SLD.cpp
+ Logging_Acceptor.cpp
+ Logging_Event_Handler.cpp
+ Logging_Handler.cpp
+ }
+}
+
+project(*SLDex) : acelib {
+ avoids += uses_wchar ace_for_tao
+ sharedname = SLDex
+ dynamicflags = SLDEX_BUILD_DLL
+ specific(gnuace) {
+ after += *CLD
+ }
+ Source_Files {
+ Logging_Acceptor.cpp
+ Logging_Event_Handler.cpp
+ Logging_Event_Handler_Ex.cpp
+ Logging_Handler.cpp
+ Reactor_Logging_Server_Adapter.cpp
+ Server_Shutdown.cpp
+ SLDex.cpp
+ }
+}
+
+project(*SR_Configurable_Log_Server) : aceexe {
+ exename = sr_configurable_logging_server
+ Source_Files {
+ SR_Configurable_Logging_Server.cpp
+ }
+}
+
+project(*TP_Reactor_Log_Server) : aceexe {
+ avoids += uses_wchar ace_for_tao
+ exename = tp_reactor_logging_server
+ specific(gnuace) {
+ after += *Reactor_Log_Server
+ }
+ Source_Files {
+ Logging_Acceptor.cpp
+ Logging_Event_Handler.cpp
+ Logging_Event_Handler_Ex.cpp
+ Logging_Handler.cpp
+ TP_Reactor_Logging_Server.cpp
+ }
+}
+
+project(*TPCLS) : acelib, ssl {
+ avoids += uses_wchar
+ sharedname = TPCLS
+ dynamicflags = TPCLS_BUILD_DLL
+ specific(gnuace) {
+ after += *CLD
+ }
+ Source_Files {
+ TPC_Logging_Server.cpp
+ Logging_Handler.cpp
+ }
+}
+
+project(*TPLS) : acelib {
+ avoids += uses_wchar ace_for_tao
+ sharedname = TPLS
+ dynamicflags = TPLS_BUILD_DLL
+ specific(gnuace) {
+ after += *CLD
+ }
+ Source_Files {
+ Logging_Acceptor.cpp
+ Logging_Event_Handler.cpp
+ Logging_Handler.cpp
+ TP_Logging_Server.cpp
+ }
+}
+
+project(*WFMO_Reactor_Log_Server) : aceexe, wfmo {
+ avoids += uses_wchar ace_for_tao
+ exename = wfmo_reactor_logging_server
+ specific(gnuace) {
+ after += *Reactor_Log_Server
+ }
+ Source_Files {
+ Logging_Acceptor.cpp
+ Logging_Event_Handler.cpp
+ Logging_Event_Handler_Ex.cpp
+ Logging_Handler.cpp
+ WFMO_Reactor_Logging_Server.cpp
+ }
+}
diff --git a/ACE/examples/C++NPv2/CLD_export.h b/ACE/examples/C++NPv2/CLD_export.h
new file mode 100644
index 00000000000..3920094e133
--- /dev/null
+++ b/ACE/examples/C++NPv2/CLD_export.h
@@ -0,0 +1,38 @@
+
+// -*- C++ -*-
+// $Id$
+// Definition for Win32 Export directives.
+// This file is generated automatically by generate_export_file.pl CLD
+// ------------------------------
+#ifndef CLD_EXPORT_H
+#define CLD_EXPORT_H
+
+#include "ace/config-all.h"
+
+#if defined (ACE_AS_STATIC_LIBS) && !defined (CLD_HAS_DLL)
+# define CLD_HAS_DLL 0
+#endif /* ACE_AS_STATIC_LIBS && ! CLD_HAS_DLL */
+
+#if !defined (CLD_HAS_DLL)
+# define CLD_HAS_DLL 1
+#endif /* ! CLD_HAS_DLL */
+
+#if defined (CLD_HAS_DLL) && (CLD_HAS_DLL == 1)
+# if defined (CLD_BUILD_DLL)
+# define CLD_Export ACE_Proper_Export_Flag
+# define CLD_SINGLETON_DECLARATION(T) ACE_EXPORT_SINGLETON_DECLARATION (T)
+# define CLD_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) ACE_EXPORT_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK)
+# else /* CLD_BUILD_DLL */
+# define CLD_Export ACE_Proper_Import_Flag
+# define CLD_SINGLETON_DECLARATION(T) ACE_IMPORT_SINGLETON_DECLARATION (T)
+# define CLD_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) ACE_IMPORT_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK)
+# endif /* CLD_BUILD_DLL */
+#else /* CLD_HAS_DLL == 1 */
+# define CLD_Export
+# define CLD_SINGLETON_DECLARATION(T)
+# define CLD_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK)
+#endif /* CLD_HAS_DLL == 1 */
+
+#endif /* CLD_EXPORT_H */
+
+// End of auto generated file.
diff --git a/ACE/examples/C++NPv2/Client_Logging_Daemon.cpp b/ACE/examples/C++NPv2/Client_Logging_Daemon.cpp
new file mode 100644
index 00000000000..5fc0d554cbd
--- /dev/null
+++ b/ACE/examples/C++NPv2/Client_Logging_Daemon.cpp
@@ -0,0 +1,379 @@
+/*
+** $Id$
+**
+** Copyright 2002 Addison Wesley. All Rights Reserved.
+*/
+
+#include "ace/os_include/os_netdb.h"
+#include "ace/OS_NS_sys_time.h"
+#include "ace/OS_NS_sys_socket.h"
+#include "ace/OS_NS_unistd.h"
+#include "ace/OS_NS_string.h"
+#include "ace/Event_Handler.h"
+#include "ace/INET_Addr.h"
+#include "ace/Get_Opt.h"
+#include "ace/Log_Record.h"
+#include "ace/Message_Block.h"
+#include "ace/Message_Queue.h"
+#include "ace/Reactor.h"
+#include "ace/Service_Object.h"
+#include "ace/Signal.h"
+#include "ace/SOCK_Acceptor.h"
+#include "ace/SOCK_Connector.h"
+#include "ace/SOCK_Stream.h"
+#include "ace/Thread_Manager.h"
+#include "Logging_Acceptor.h"
+#include "CLD_export.h"
+
+#if !defined (FLUSH_TIMEOUT)
+#define FLUSH_TIMEOUT 120 /* 120 seconds == 2 minutes. */
+#endif /* FLUSH_TIMEOUT */
+
+
+class CLD_Connector;
+
+class CLD_Handler : public ACE_Event_Handler {
+public:
+ enum { QUEUE_MAX = sizeof (ACE_Log_Record) * ACE_IOV_MAX };
+
+ // Initialization hook method.
+ virtual int open (CLD_Connector *);
+ virtual int close (); // Shut down hook method.
+
+ // Accessor to the connection to the logging server.
+ virtual ACE_SOCK_Stream &peer () { return peer_; }
+
+ // Reactor hook methods.
+ virtual int handle_input (ACE_HANDLE handle);
+ virtual int handle_close (ACE_HANDLE = ACE_INVALID_HANDLE,
+ ACE_Reactor_Mask = 0);
+
+protected:
+ // Forward log records to the server logging daemon.
+ virtual ACE_THR_FUNC_RETURN forward ();
+
+ // Send the buffered log records using a gather-write operation.
+ virtual int send (ACE_Message_Block *chunk[], size_t &count);
+
+ // Entry point into forwarder thread of control.
+ static ACE_THR_FUNC_RETURN run_svc (void *arg);
+
+ // A synchronized <ACE_Message_Queue> that queues messages.
+ ACE_Message_Queue<ACE_SYNCH> msg_queue_;
+
+ // Manage the forwarder thread.
+ ACE_Thread_Manager thr_mgr_;
+
+ // Pointer to our <CLD_Connector>.
+ CLD_Connector *connector_;
+
+ // Connection to the logging server.
+ ACE_SOCK_Stream peer_;
+};
+
+
+class CLD_Connector {
+public:
+ // Establish a connection to the logging server
+ // at the <remote_addr>.
+ int connect (CLD_Handler *handler,
+ const ACE_INET_Addr &remote_addr);
+
+ // Re-establish a connection to the logging server.
+ int reconnect ();
+
+private:
+ // Pointer to the <CLD_Handler> that we're connecting.
+ CLD_Handler *handler_;
+
+ // Address at which the logging server is listening
+ // for connections.
+ ACE_INET_Addr remote_addr_;
+};
+
+
+class CLD_Acceptor : public ACE_Event_Handler {
+public:
+ // Initialization hook method.
+ virtual int open (CLD_Handler *, const ACE_INET_Addr &,
+ ACE_Reactor * = ACE_Reactor::instance ());
+
+ // Reactor hook methods.
+ virtual int handle_input (ACE_HANDLE handle);
+ virtual int handle_close (ACE_HANDLE = ACE_INVALID_HANDLE,
+ ACE_Reactor_Mask = 0);
+ virtual ACE_HANDLE get_handle () const;
+
+protected:
+ // Factory that passively connects <ACE_SOCK_Stream>s.
+ ACE_SOCK_Acceptor acceptor_;
+
+ // Pointer to the handler of log records.
+ CLD_Handler *handler_;
+};
+
+/****************************************************/
+
+int CLD_Handler::handle_input (ACE_HANDLE handle) {
+ ACE_Message_Block *mblk = 0;
+ Logging_Handler logging_handler (handle);
+
+ if (logging_handler.recv_log_record (mblk) != -1)
+ if (msg_queue_.enqueue_tail (mblk->cont ()) != -1) {
+ mblk->cont (0);
+ mblk->release ();
+ return 0; // Success return.
+ } else mblk->release ();
+ return -1; // Error return.
+}
+
+
+int CLD_Handler::handle_close (ACE_HANDLE handle,
+ ACE_Reactor_Mask)
+{ return ACE_OS::closesocket (handle); }
+
+
+int CLD_Handler::open (CLD_Connector *connector) {
+ connector_ = connector;
+ int bufsiz = ACE_DEFAULT_MAX_SOCKET_BUFSIZ;
+ peer ().set_option (SOL_SOCKET, SO_SNDBUF,
+ &bufsiz, sizeof bufsiz);
+ msg_queue_.high_water_mark (CLD_Handler::QUEUE_MAX);
+ return thr_mgr_.spawn (&CLD_Handler::run_svc,
+ this, THR_SCOPE_SYSTEM);
+}
+
+
+ACE_THR_FUNC_RETURN CLD_Handler::run_svc (void *arg) {
+ CLD_Handler *handler = static_cast<CLD_Handler *> (arg);
+ return handler->forward ();
+}
+
+
+ACE_THR_FUNC_RETURN CLD_Handler::forward () {
+ ACE_Message_Block *chunk[ACE_IOV_MAX];
+ size_t message_index = 0;
+ ACE_Time_Value time_of_last_send (ACE_OS::gettimeofday ());
+ ACE_Time_Value timeout;
+ ACE_Sig_Action no_sigpipe ((ACE_SignalHandler) SIG_IGN);
+ ACE_Sig_Action original_action;
+ no_sigpipe.register_action (SIGPIPE, &original_action);
+
+ for (;;) {
+ if (message_index == 0) {
+ timeout = ACE_OS::gettimeofday ();
+ timeout += FLUSH_TIMEOUT;
+ }
+ ACE_Message_Block *mblk = 0;
+ if (msg_queue_.dequeue_head (mblk, &timeout) == -1) {
+ if (errno != EWOULDBLOCK) break;
+ else if (message_index == 0) continue;
+ } else {
+ if (mblk->size () == 0
+ && mblk->msg_type () == ACE_Message_Block::MB_STOP)
+ { mblk->release (); break; }
+ chunk[message_index] = mblk;
+ ++message_index;
+ }
+ if (message_index >= ACE_IOV_MAX ||
+ (ACE_OS::gettimeofday () - time_of_last_send
+ >= ACE_Time_Value(FLUSH_TIMEOUT))) {
+ if (send (chunk, message_index) == -1) break;
+ time_of_last_send = ACE_OS::gettimeofday ();
+ }
+ }
+
+ if (message_index > 0) send (chunk, message_index);
+ msg_queue_.close ();
+ no_sigpipe.restore_action (SIGPIPE, original_action);
+ return 0;
+}
+
+
+int CLD_Handler::send (ACE_Message_Block *chunk[], size_t &count) {
+ iovec iov[ACE_IOV_MAX];
+ size_t iov_size;
+ int result = 0;
+
+ for (iov_size = 0; iov_size < count; ++iov_size) {
+ iov[iov_size].iov_base = chunk[iov_size]->rd_ptr ();
+ iov[iov_size].iov_len = chunk[iov_size]->length ();
+ }
+ while (peer ().sendv_n (iov, iov_size) == -1)
+ if (connector_->reconnect () == -1) {
+ result = -1;
+ break;
+ }
+
+ while (iov_size > 0) {
+ chunk[--iov_size]->release (); chunk[iov_size] = 0;
+ }
+ count = iov_size;
+ return result;
+}
+
+
+int CLD_Handler::close () {
+ ACE_Message_Block *shutdown_message = 0;
+ ACE_NEW_RETURN
+ (shutdown_message,
+ ACE_Message_Block (0, ACE_Message_Block::MB_STOP), -1);
+ msg_queue_.enqueue_tail (shutdown_message);
+ return thr_mgr_.wait ();
+}
+
+/**************************************************************/
+
+
+int CLD_Acceptor::open (CLD_Handler *handler,
+ const ACE_INET_Addr &local_addr,
+ ACE_Reactor *r) {
+ reactor (r); // Store the reactor pointer.
+ handler_ = handler;
+ if (acceptor_.open (local_addr) == -1
+ || reactor ()->register_handler
+ (this, ACE_Event_Handler::ACCEPT_MASK) == -1)
+ return -1;
+ return 0;
+}
+
+
+ACE_HANDLE CLD_Acceptor::get_handle () const
+{ return acceptor_.get_handle (); }
+
+
+int CLD_Acceptor::handle_input (ACE_HANDLE) {
+ ACE_SOCK_Stream peer_stream;
+ if (acceptor_.accept (peer_stream) == -1) return -1;
+ else if (reactor ()->register_handler
+ (peer_stream.get_handle (),
+ handler_,
+ ACE_Event_Handler::READ_MASK) == -1)
+ return -1;
+ else return 0;
+}
+
+
+int CLD_Acceptor::handle_close (ACE_HANDLE, ACE_Reactor_Mask) {
+ acceptor_.close ();
+ handler_->close ();
+ return 0;
+}
+
+
+/***************************************************/
+
+
+int CLD_Connector::connect
+ (CLD_Handler *handler,
+ const ACE_INET_Addr &remote_addr) {
+ ACE_SOCK_Connector connector;
+
+ if (connector.connect (handler->peer (), remote_addr) == -1)
+ return -1;
+ else if (handler->open (this) == -1)
+ { handler->handle_close (); return -1; }
+ handler_ = handler;
+ remote_addr_ = remote_addr;
+ return 0;
+}
+
+
+int CLD_Connector::reconnect () {
+ // Maximum number of times to retry connect.
+ const size_t MAX_RETRIES = 5;
+
+ ACE_SOCK_Connector connector;
+ ACE_Time_Value timeout (1); // Start with 1 second timeout.
+ size_t i;
+ for (i = 0; i < MAX_RETRIES; ++i) {
+ if (i > 0) ACE_OS::sleep (timeout);
+ if (connector.connect (handler_->peer (), remote_addr_,
+ &timeout) == -1)
+ timeout *= 2; // Exponential backoff.
+ else {
+ int bufsiz = ACE_DEFAULT_MAX_SOCKET_BUFSIZ;
+ handler_->peer ().set_option (SOL_SOCKET, SO_SNDBUF,
+ &bufsiz, sizeof bufsiz);
+ break;
+ }
+ }
+ return i == MAX_RETRIES ? -1 : 0;
+}
+
+
+/*******************************************************/
+
+class Client_Logging_Daemon : public ACE_Service_Object {
+public:
+ virtual ~Client_Logging_Daemon () {} // Turn off g++ warnings.
+
+ // Service Configurator hook methods.
+ virtual int init (int argc, ACE_TCHAR *argv[]);
+ virtual int fini ();
+#if 0
+ // Implementing these methods is left as an exercise for the reader.
+ virtual int info (ACE_TCHAR **bufferp, size_t length = 0) const;
+ virtual int suspend ();
+ virtual int resume ();
+#endif
+
+protected:
+ // Receives, processes, and forwards log records.
+ CLD_Handler handler_;
+
+ // Factory that passively connects the <CLD_Handler>.
+ CLD_Acceptor acceptor_;
+
+ // Factory that actively connects the <CLD_Handler>.
+ CLD_Connector connector_;
+};
+
+
+int Client_Logging_Daemon::init (int argc, ACE_TCHAR *argv[]) {
+ u_short cld_port = ACE_DEFAULT_SERVICE_PORT;
+ u_short sld_port = ACE_DEFAULT_LOGGING_SERVER_PORT;
+ ACE_TCHAR sld_host[MAXHOSTNAMELEN];
+ ACE_OS::strcpy (sld_host, ACE_LOCALHOST);
+
+ ACE_Get_Opt get_opt (argc, argv, ACE_TEXT ("p:r:s:"), 0);
+ get_opt.long_option (ACE_TEXT ("client_port"), 'p',
+ ACE_Get_Opt::ARG_REQUIRED);
+ get_opt.long_option (ACE_TEXT ("server_port"), 'r',
+ ACE_Get_Opt::ARG_REQUIRED);
+ get_opt.long_option (ACE_TEXT ("server_name"), 's',
+ ACE_Get_Opt::ARG_REQUIRED);
+
+ for (int c; (c = get_opt ()) != -1;)
+ switch (c) {
+ case 'p': // Client logging daemon acceptor port number.
+ cld_port = static_cast<u_short> (ACE_OS::atoi (get_opt.opt_arg ()));
+ break;
+ case 'r': // Server logging daemon acceptor port number.
+ sld_port = static_cast<u_short> (ACE_OS::atoi (get_opt.opt_arg ()));
+ break;
+ case 's': // Server logging daemon hostname.
+ ACE_OS::strsncpy
+ (sld_host, get_opt.opt_arg (), MAXHOSTNAMELEN);
+ break;
+ }
+
+ ACE_INET_Addr cld_addr (cld_port);
+ ACE_INET_Addr sld_addr (sld_port, sld_host);
+
+ if (acceptor_.open (&handler_, cld_addr) == -1)
+ return -1;
+ else if (connector_.connect (&handler_, sld_addr) == -1)
+ { acceptor_.handle_close (); return -1; }
+ return 0;
+}
+
+
+int Client_Logging_Daemon::fini () {
+ acceptor_.handle_close ();
+ handler_.close ();
+ return 0;
+}
+
+
+ACE_FACTORY_DEFINE (CLD, Client_Logging_Daemon)
diff --git a/ACE/examples/C++NPv2/Configurable_Logging_Server.cpp b/ACE/examples/C++NPv2/Configurable_Logging_Server.cpp
new file mode 100644
index 00000000000..bcd6d42b884
--- /dev/null
+++ b/ACE/examples/C++NPv2/Configurable_Logging_Server.cpp
@@ -0,0 +1,20 @@
+/*
+** $Id$
+**
+** Copyright 2002 Addison Wesley. All Rights Reserved.
+*/
+
+#include "ace/OS_main.h"
+#include "ace/Service_Config.h"
+#include "ace/Reactor.h"
+
+int ACE_TMAIN (int argc, ACE_TCHAR *argv[]) {
+
+ ACE_STATIC_SVC_REGISTER (Reporter_Descriptor);
+
+ ACE_Service_Config::open
+ (argc, argv, ACE_DEFAULT_LOGGER_KEY, 0);
+
+ ACE_Reactor::instance ()->run_reactor_event_loop ();
+ return 0;
+}
diff --git a/ACE/examples/C++NPv2/Logging_Acceptor.cpp b/ACE/examples/C++NPv2/Logging_Acceptor.cpp
new file mode 100644
index 00000000000..2e7b7479603
--- /dev/null
+++ b/ACE/examples/C++NPv2/Logging_Acceptor.cpp
@@ -0,0 +1,38 @@
+/*
+** $Id$
+**
+** Copyright 2002 Addison Wesley. All Rights Reserved.
+*/
+
+#include "Logging_Acceptor.h"
+#include "Logging_Event_Handler.h"
+
+
+int Logging_Acceptor::open (const ACE_INET_Addr &local_addr) {
+ if (acceptor_.open (local_addr) == -1) return -1;
+ return reactor ()->register_handler
+ (this, ACE_Event_Handler::ACCEPT_MASK);
+}
+
+int Logging_Acceptor::handle_input (ACE_HANDLE) {
+ Logging_Event_Handler *peer_handler = 0;
+ ACE_NEW_RETURN (peer_handler,
+ Logging_Event_Handler (reactor ()),
+ -1);
+
+ if (acceptor_.accept (peer_handler->peer ()) == -1) {
+ delete peer_handler;
+ return -1;
+ } else if (peer_handler->open () == -1) {
+ peer_handler->handle_close ();
+ return -1;
+ }
+ return 0;
+}
+
+int Logging_Acceptor::handle_close (ACE_HANDLE,
+ ACE_Reactor_Mask) {
+ acceptor_.close ();
+ delete this;
+ return 0;
+}
diff --git a/ACE/examples/C++NPv2/Logging_Acceptor.h b/ACE/examples/C++NPv2/Logging_Acceptor.h
new file mode 100644
index 00000000000..7d38439e3eb
--- /dev/null
+++ b/ACE/examples/C++NPv2/Logging_Acceptor.h
@@ -0,0 +1,53 @@
+/*
+** $Id$
+**
+** Copyright 2002 Addison Wesley. All Rights Reserved.
+*/
+
+#ifndef _LOGGING_ACCEPTOR_H
+#define _LOGGING_ACCEPTOR_H
+
+#include "ace/Event_Handler.h"
+#include "ace/INET_Addr.h"
+#include "ace/Log_Record.h"
+#include "ace/Reactor.h"
+#include "ace/SOCK_Acceptor.h"
+#include "ace/SOCK_Stream.h"
+#include "Logging_Handler.h"
+
+class Logging_Acceptor : public ACE_Event_Handler
+{
+protected:
+ // Factory that connects <ACE_SOCK_Stream>s passively.
+ ACE_SOCK_Acceptor acceptor_;
+
+protected:
+ virtual ~Logging_Acceptor () {}; // No-op destructor.
+
+public:
+ typedef ACE_INET_Addr PEER_ADDR;
+
+ // Simple constructor.
+ Logging_Acceptor (ACE_Reactor *r = ACE_Reactor::instance ())
+ : ACE_Event_Handler (r) {};
+
+ // Initialization method.
+ virtual int open (const ACE_INET_Addr &local_addr);
+
+ // Called by a reactor when there's a new connection to accept.
+ virtual int handle_input (ACE_HANDLE = ACE_INVALID_HANDLE);
+
+ // Called when this object is destroyed, e.g., when it's
+ // removed from a reactor.
+ virtual int handle_close (ACE_HANDLE = ACE_INVALID_HANDLE,
+ ACE_Reactor_Mask = 0);
+
+ // Return the passive-mode socket's I/O handle.
+ virtual ACE_HANDLE get_handle () const
+ { return acceptor_.get_handle (); };
+
+ // Returns a reference to the underlying <acceptor_>.
+ ACE_SOCK_Acceptor &acceptor () { return acceptor_; };
+};
+
+#endif /* _LOGGING_ACCEPTOR_H */
diff --git a/ACE/examples/C++NPv2/Logging_Acceptor_Ex.h b/ACE/examples/C++NPv2/Logging_Acceptor_Ex.h
new file mode 100644
index 00000000000..913ae385db6
--- /dev/null
+++ b/ACE/examples/C++NPv2/Logging_Acceptor_Ex.h
@@ -0,0 +1,41 @@
+/*
+** $Id$
+**
+** Copyright 2002 Addison Wesley. All Rights Reserved.
+*/
+
+#ifndef _LOGGING_ACCEPTOR_EX_H
+#define _LOGGING_ACCEPTOR_EX_H
+
+#include "ace/INET_Addr.h"
+#include "ace/Reactor.h"
+
+#include "Logging_Acceptor.h"
+#include "Logging_Event_Handler_Ex.h"
+
+class Logging_Acceptor_Ex : public Logging_Acceptor
+{
+public:
+ typedef ACE_INET_Addr PEER_ADDR;
+
+ // Simple constructor to pass ACE_Reactor to base class.
+ Logging_Acceptor_Ex (ACE_Reactor *r = ACE_Reactor::instance ())
+ : Logging_Acceptor (r) {}
+
+ int handle_input (ACE_HANDLE) {
+ Logging_Event_Handler_Ex *peer_handler = 0;
+ ACE_NEW_RETURN (peer_handler,
+ Logging_Event_Handler_Ex (reactor ()),
+ -1);
+ if (acceptor_.accept (peer_handler->peer ()) == -1) {
+ delete peer_handler;
+ return -1;
+ } else if (peer_handler->open () == -1) {
+ peer_handler->handle_close ();
+ return -1;
+ }
+ return 0;
+ }
+};
+
+#endif /* _LOGGING_ACCEPTOR_EX_H */
diff --git a/ACE/examples/C++NPv2/Logging_Event_Handler.cpp b/ACE/examples/C++NPv2/Logging_Event_Handler.cpp
new file mode 100644
index 00000000000..d805e776390
--- /dev/null
+++ b/ACE/examples/C++NPv2/Logging_Event_Handler.cpp
@@ -0,0 +1,45 @@
+/*
+** $Id$
+**
+** Copyright 2002 Addison Wesley. All Rights Reserved.
+*/
+
+#include "ace/FILE_Connector.h"
+
+#include "Logging_Event_Handler.h"
+#include "ace/OS_NS_string.h"
+#include "ace/os_include/os_netdb.h"
+
+int Logging_Event_Handler::open () {
+
+ static const char LOGFILE_SUFFIX[] = ".log";
+ char filename[MAXHOSTNAMELEN + sizeof (LOGFILE_SUFFIX)];
+ ACE_INET_Addr logging_peer_addr;
+
+ logging_handler_.peer ().get_remote_addr (logging_peer_addr);
+ logging_peer_addr.get_host_name (filename, MAXHOSTNAMELEN);
+ ACE_OS::strcat (filename, LOGFILE_SUFFIX);
+
+ ACE_FILE_Connector connector;
+ connector.connect (log_file_,
+ ACE_FILE_Addr (filename),
+ 0, // No timeout.
+ ACE_Addr::sap_any, // Ignored.
+ 0, // Don't try to reuse the addr.
+ O_RDWR|O_CREAT|O_APPEND,
+ ACE_DEFAULT_FILE_PERMS);
+
+ return reactor ()->register_handler
+ (this, ACE_Event_Handler::READ_MASK);
+}
+
+int Logging_Event_Handler::handle_input (ACE_HANDLE)
+{ return logging_handler_.log_record (); }
+
+int Logging_Event_Handler::handle_close (ACE_HANDLE,
+ ACE_Reactor_Mask) {
+ logging_handler_.close ();
+ log_file_.close ();
+ delete this;
+ return 0;
+}
diff --git a/ACE/examples/C++NPv2/Logging_Event_Handler.h b/ACE/examples/C++NPv2/Logging_Event_Handler.h
new file mode 100644
index 00000000000..f1a71364be5
--- /dev/null
+++ b/ACE/examples/C++NPv2/Logging_Event_Handler.h
@@ -0,0 +1,61 @@
+/*
+** $Id$
+**
+** Copyright 2002 Addison Wesley. All Rights Reserved.
+*/
+
+#ifndef _LOGGING_EVENT_HANDLER_H
+#define _LOGGING_EVENT_HANDLER_H
+
+#include "ace/Event_Handler.h"
+#include "ace/FILE_IO.h"
+#include "ace/Reactor.h"
+#include "ace/SOCK_Stream.h"
+
+#include "Logging_Handler.h"
+
+class Logging_Event_Handler : public ACE_Event_Handler
+{
+protected:
+ // File where log records are written.
+ ACE_FILE_IO log_file_;
+
+ // Connection to remote peer.
+ Logging_Handler logging_handler_;
+
+public:
+ // Initialize the base class and logging handler.
+ Logging_Event_Handler (ACE_Reactor *reactor)
+ : ACE_Event_Handler (reactor),
+ logging_handler_ (log_file_) {};
+
+ virtual ~Logging_Event_Handler () {}; // No-op destructor.
+
+ // Activate the object.
+ virtual int open ();
+
+ // Called by a reactor when logging events arrive.
+ virtual int handle_input (ACE_HANDLE = ACE_INVALID_HANDLE);
+
+ // Called when this object is destroyed, e.g., when it's
+ // removed from a reactor.
+ virtual int handle_close (ACE_HANDLE = ACE_INVALID_HANDLE,
+ ACE_Reactor_Mask = 0);
+
+ // Return socket handle of the contained <Logging_Handler>.
+ virtual ACE_HANDLE get_handle (void) const {
+ // Need a non-const reference to call peer(), but that's
+ // safe since we call a const method using it.
+ Logging_Handler& h =
+ const_cast<Logging_Handler&> (logging_handler_);
+ return h.peer ().get_handle ();
+ };
+
+ // Get a reference to the contained <ACE_SOCK_Stream>.
+ ACE_SOCK_Stream &peer () { return logging_handler_.peer (); };
+
+ // Return a reference to the <log_file_>.
+ ACE_FILE_IO &log_file () { return log_file_; };
+};
+
+#endif /* _LOGGING_EVENT_HANDLER_H */
diff --git a/ACE/examples/C++NPv2/Logging_Event_Handler_Ex.cpp b/ACE/examples/C++NPv2/Logging_Event_Handler_Ex.cpp
new file mode 100644
index 00000000000..858e615e9d9
--- /dev/null
+++ b/ACE/examples/C++NPv2/Logging_Event_Handler_Ex.cpp
@@ -0,0 +1,41 @@
+/*
+** $Id$
+**
+** Copyright 2002 Addison Wesley. All Rights Reserved.
+*/
+
+#include "Logging_Event_Handler_Ex.h"
+#include "ace/Timer_Queue.h"
+
+int Logging_Event_Handler_Ex::handle_input (ACE_HANDLE h) {
+ time_of_last_log_record_ =
+ reactor ()->timer_queue ()->gettimeofday ();
+ return PARENT::handle_input (h);
+}
+
+int Logging_Event_Handler_Ex::open () {
+ int result = PARENT::open ();
+ if (result != -1) {
+ ACE_Time_Value reschedule (max_client_timeout_.sec () / 4);
+ result =
+ reactor ()->schedule_timer
+ (this,
+ 0,
+ max_client_timeout_, // Initial timeout.
+ reschedule); // Subsequent timeouts.
+ }
+ return result;
+}
+
+int Logging_Event_Handler_Ex::handle_timeout
+ (const ACE_Time_Value &now, const void *) {
+ if (now - time_of_last_log_record_ >= max_client_timeout_)
+ reactor ()->remove_handler (this, ACE_Event_Handler::READ_MASK);
+ return 0;
+}
+
+int Logging_Event_Handler_Ex::handle_close (ACE_HANDLE,
+ ACE_Reactor_Mask) {
+ reactor ()->cancel_timer (this);
+ return PARENT::handle_close ();
+}
diff --git a/ACE/examples/C++NPv2/Logging_Event_Handler_Ex.h b/ACE/examples/C++NPv2/Logging_Event_Handler_Ex.h
new file mode 100644
index 00000000000..d6639cf78d2
--- /dev/null
+++ b/ACE/examples/C++NPv2/Logging_Event_Handler_Ex.h
@@ -0,0 +1,57 @@
+/*
+** $Id$
+**
+** Copyright 2002 Addison Wesley. All Rights Reserved.
+*/
+
+#ifndef _LOGGING_EVENT_HANDLER_EX_H
+#define _LOGGING_EVENT_HANDLER_EX_H
+
+#include "ace/Reactor.h"
+#include "ace/Time_Value.h"
+#include "ace/Recursive_Thread_Mutex.h"
+
+#include "Logging_Event_Handler.h"
+
+class Logging_Event_Handler_Ex : public Logging_Event_Handler
+{
+private:
+ // Time when a client last sent a log record.
+ ACE_Time_Value time_of_last_log_record_;
+
+ // Maximum time to wait for a client log record.
+ const ACE_Time_Value max_client_timeout_;
+
+public:
+ typedef Logging_Event_Handler PARENT;
+
+ // 3600 seconds == one hour.
+ enum { MAX_CLIENT_TIMEOUT = 3600 };
+
+ Logging_Event_Handler_Ex
+ (ACE_Reactor *reactor,
+ const ACE_Time_Value &max_client_timeout
+ = ACE_Time_Value (MAX_CLIENT_TIMEOUT))
+ : Logging_Event_Handler (reactor),
+ time_of_last_log_record_ (0),
+ max_client_timeout_ (max_client_timeout) {}
+
+ virtual ~Logging_Event_Handler_Ex () {}
+
+ virtual int open (); // Activate the event handler.
+
+ // Called by a reactor when logging events arrive.
+ virtual int handle_input (ACE_HANDLE);
+
+ // Called when a timeout expires to check if the client has
+ // been idle for an excessive amount of time.
+ virtual int handle_timeout (const ACE_Time_Value &tv,
+ const void *act);
+
+ // Called when this object is destroyed, e.g., when it's
+ // removed from a reactor.
+ virtual int handle_close (ACE_HANDLE = ACE_INVALID_HANDLE,
+ ACE_Reactor_Mask = 0);
+};
+
+#endif /* _LOGGING_EVENT_HANDLER_EX_H */
diff --git a/ACE/examples/C++NPv2/Logging_Handler.cpp b/ACE/examples/C++NPv2/Logging_Handler.cpp
new file mode 100644
index 00000000000..a3febb8234d
--- /dev/null
+++ b/ACE/examples/C++NPv2/Logging_Handler.cpp
@@ -0,0 +1,110 @@
+/*
+** $Id$
+**
+** Copyright 2001 Addison Wesley. All Rights Reserved.
+*/
+
+#include "ace/ACE.h"
+#include "ace/CDR_Stream.h"
+#include "ace/INET_Addr.h"
+#include "ace/Log_Record.h"
+#include "ace/Message_Block.h"
+
+// FUZZ: disable check_for_streams_include
+#include "ace/streams.h"
+
+#include "Logging_Handler.h"
+#include "ace/os_include/os_netdb.h"
+#include "ace/OS_NS_string.h"
+
+int Logging_Handler::recv_log_record (ACE_Message_Block *&mblk)
+{
+ // Put <logging_peer>'s hostname in new message block.
+ ACE_INET_Addr peer_addr;
+ logging_peer_.get_remote_addr (peer_addr);
+ mblk = new ACE_Message_Block (MAXHOSTNAMELEN + 1);
+ peer_addr.get_host_name (mblk->wr_ptr (), MAXHOSTNAMELEN);
+ mblk->wr_ptr (ACE_OS::strlen (mblk->wr_ptr ()) + 1); // Go past name
+
+ // Allocate a message block for the payload; initially at least
+ // large enough to hold the header, but needs some room for
+ // alignment.
+ ACE_Message_Block *payload =
+ new ACE_Message_Block (ACE_DEFAULT_CDR_BUFSIZE);
+ // Align the Message Block for a CDR stream
+ ACE_CDR::mb_align (payload);
+ if (logging_peer_.recv_n (payload->wr_ptr (), 8) == 8) {
+ payload->wr_ptr (8); // Reflect addition of 8 bytes
+
+ // Create a CDR stream to parse the 8-byte header.
+ ACE_InputCDR cdr (payload);
+
+ // Extract the byte-order and use helper methods to
+ // disambiguate octet, booleans, and chars.
+ ACE_CDR::Boolean byte_order;
+ cdr >> ACE_InputCDR::to_boolean (byte_order);
+
+ // Set the byte-order on the stream...
+ cdr.reset_byte_order (byte_order);
+
+ // Extract the length
+ ACE_CDR::ULong length;
+ cdr >> length;
+
+ // Ensure there's sufficient room for log record payload.
+ ACE_CDR::grow (payload, 8 + ACE_CDR::MAX_ALIGNMENT + length);
+
+ // Use <recv_n> to obtain the contents.
+ if (logging_peer_.recv_n (payload->wr_ptr (), length) > 0) {
+ payload->wr_ptr (length); // Reflect additional bytes
+ // Chain the payload to mblk via the contination field.
+ mblk->cont (payload);
+ return length;
+ }
+ }
+ // Error cases end up here, so we need to release the memory to
+ // prevent a leak.
+ payload->release ();
+ payload = 0;
+ mblk->release ();
+ mblk = 0;
+ return -1;
+}
+
+
+int Logging_Handler::write_log_record (ACE_Message_Block *mblk)
+{
+ // Peer hostname is in the <mblk> and the log record data
+ // is in its continuation.
+ if (log_file_->send_n (mblk) == -1)
+ return -1;
+ if (ACE::debug ()) {
+ // Build a CDR stream from the log record data.
+ ACE_InputCDR cdr (mblk->cont ());
+ ACE_CDR::Boolean byte_order;
+ ACE_CDR::ULong length;
+ // Extract the byte-order and length, ending up at the start
+ // of the log record itself. Use the byte order to properly
+ // set the CDR stream for extracting the contents.
+ cdr >> ACE_InputCDR::to_boolean (byte_order);
+ cdr.reset_byte_order (byte_order);
+ cdr >> length;
+ ACE_Log_Record log_record;
+ cdr >> log_record; // Finally extract the <ACE_log_record>.
+ log_record.print (mblk->rd_ptr (), 1, cerr);
+ }
+ return mblk->total_length ();
+}
+
+
+int Logging_Handler::log_record ()
+{
+ ACE_Message_Block *mblk = 0;
+ if (recv_log_record (mblk) == -1)
+ return -1;
+ else {
+ int result = write_log_record (mblk);
+ mblk->release (); // Free up the contents.
+ return result == -1 ? -1 : 0;
+ }
+}
diff --git a/ACE/examples/C++NPv2/Logging_Handler.h b/ACE/examples/C++NPv2/Logging_Handler.h
new file mode 100644
index 00000000000..41945c3a182
--- /dev/null
+++ b/ACE/examples/C++NPv2/Logging_Handler.h
@@ -0,0 +1,57 @@
+/*
+** $Id$
+**
+** Copyright 2001 Addison Wesley. All Rights Reserved.
+*/
+
+#ifndef _LOGGING_HANDLER_H
+#define _LOGGING_HANDLER_H
+
+#include "ace/FILE_IO.h"
+#include "ace/SOCK_Stream.h"
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+class ACE_Message_Block;
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+class Logging_Handler
+{
+protected:
+ ACE_FILE_IO *log_file_; // Pointer to a log file.
+
+ ACE_SOCK_Stream logging_peer_; // Connected to the client.
+
+public:
+ // Initialization and termination methods.
+ Logging_Handler (ACE_FILE_IO &log_file): log_file_ (&log_file) {};
+ Logging_Handler (ACE_FILE_IO &log_file,
+ ACE_HANDLE handle): log_file_ (&log_file)
+ { logging_peer_.set_handle (handle); };
+ Logging_Handler (ACE_FILE_IO &log_file,
+ const ACE_SOCK_Stream &logging_peer)
+ : log_file_ (&log_file), logging_peer_ (logging_peer) {};
+ Logging_Handler (const ACE_SOCK_Stream &logging_peer)
+ : log_file_ (0), logging_peer_ (logging_peer) {};
+ int close () { return logging_peer_.close (); };
+
+ // Receive one log record from a connected client. Returns
+ // length of record on success and <mblk> contains the
+ // hostname, <mblk->cont()> contains the log record header
+ // (the byte order and the length) and the data. Returns -1 on
+ // failure or connection close.
+ int recv_log_record (ACE_Message_Block *&log_record);
+
+ // Write one record to the log file. The <mblk> contains the
+ // hostname and the <mblk->cont> contains the log record.
+ // Returns length of record written on success, or -1 on failure.
+ int write_log_record (ACE_Message_Block *log_record);
+
+ // Log one record by calling <recv_log_record> and
+ // <write_log_record>. Returns 0 on success and -1 on failure.
+ int log_record ();
+
+ // Accessor method.
+ ACE_SOCK_Stream &peer () { return logging_peer_; };
+};
+
+#endif /* _LOGGING_HANDLER_H */
diff --git a/ACE/examples/C++NPv2/Makefile.am b/ACE/examples/C++NPv2/Makefile.am
new file mode 100644
index 00000000000..e15da126644
--- /dev/null
+++ b/ACE/examples/C++NPv2/Makefile.am
@@ -0,0 +1,424 @@
+## Process this file with automake to create Makefile.in
+##
+## $Id$
+##
+## This file was generated by MPC. Any changes made directly to
+## this file will be lost the next time it is generated.
+##
+## MPC Command:
+## /acebuilds/ACE_wrappers-repository/bin/mwc.pl -include /acebuilds/MPC/config -include /acebuilds/MPC/templates -feature_file /acebuilds/ACE_wrappers-repository/local.features -noreldefs -type automake -exclude build,Kokyu
+
+ACE_BUILDDIR = $(top_builddir)
+ACE_ROOT = $(top_srcdir)
+
+noinst_HEADERS =
+noinst_LTLIBRARIES =
+noinst_PROGRAMS =
+
+## Makefile.C++NPv2_AC_CLD.am
+
+if BUILD_SSL
+if !BUILD_ACE_FOR_TAO
+if !BUILD_USES_WCHAR
+
+noinst_LTLIBRARIES += libAC_CLD.la
+
+libAC_CLD_la_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR) \
+ -DACE_HAS_SSL=1 \
+ @ACE_TLS_CPPFLAGS@ \
+ -DAC_CLD_BUILD_DLL
+
+libAC_CLD_la_SOURCES = \
+ AC_Client_Logging_Daemon.cpp \
+ Logging_Handler.cpp
+
+libAC_CLD_la_LDFLAGS = \
+ @ACE_TLS_LDFLAGS@
+
+noinst_HEADERS += \
+ AC_Client_Logging_Daemon.h \
+ Logging_Handler.h \
+ Reactor_Logging_Server_T.cpp
+
+endif !BUILD_USES_WCHAR
+endif !BUILD_ACE_FOR_TAO
+endif BUILD_SSL
+
+## Makefile.C++NPv2_AIO_CLD.am
+
+if BUILD_SSL
+if !BUILD_ACE_FOR_TAO
+
+noinst_LTLIBRARIES += libAIO_CLD.la
+
+libAIO_CLD_la_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR) \
+ -DACE_HAS_SSL=1 \
+ @ACE_TLS_CPPFLAGS@ \
+ -DAIO_CLD_BUILD_DLL
+
+libAIO_CLD_la_SOURCES = \
+ AIO_Client_Logging_Daemon.cpp
+
+libAIO_CLD_la_LDFLAGS = \
+ @ACE_TLS_LDFLAGS@
+
+noinst_HEADERS += \
+ AIO_Client_Logging_Daemon.h \
+ Reactor_Logging_Server_T.cpp
+
+endif !BUILD_ACE_FOR_TAO
+endif BUILD_SSL
+
+## Makefile.C++NPv2_CLD.am
+
+if !BUILD_ACE_FOR_TAO
+if !BUILD_USES_WCHAR
+
+noinst_LTLIBRARIES += libCLD.la
+
+libCLD_la_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR) \
+ -DCLD_BUILD_DLL
+
+libCLD_la_SOURCES = \
+ Client_Logging_Daemon.cpp \
+ Logging_Acceptor.cpp \
+ Logging_Event_Handler.cpp \
+ Logging_Handler.cpp
+
+noinst_HEADERS += \
+ Logging_Acceptor.h \
+ Logging_Event_Handler.h \
+ Logging_Handler.h \
+ Reactor_Logging_Server_T.cpp
+
+endif !BUILD_USES_WCHAR
+endif !BUILD_ACE_FOR_TAO
+
+## Makefile.C++NPv2_Configurable_Log_Server.am
+
+if !BUILD_USES_WCHAR
+noinst_PROGRAMS += configurable_logging_server
+
+configurable_logging_server_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+configurable_logging_server_SOURCES = \
+ Configurable_Logging_Server.cpp \
+ Service_Reporter.cpp \
+ Service_Reporter.h
+
+configurable_logging_server_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+endif !BUILD_USES_WCHAR
+
+## Makefile.C++NPv2_Display_Logfile.am
+
+if !BUILD_ACE_FOR_TAO
+noinst_PROGRAMS += display_logfile
+
+display_logfile_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+display_logfile_SOURCES = \
+ display_logfile.cpp \
+ AC_CLD_export.h \
+ AC_Client_Logging_Daemon.h \
+ AIO_CLD_export.h \
+ AIO_Client_Logging_Daemon.h \
+ CLD_export.h \
+ Logging_Acceptor.h \
+ Logging_Acceptor_Ex.h \
+ Logging_Event_Handler.h \
+ Logging_Event_Handler_Ex.h \
+ Logging_Handler.h \
+ Reactor_Logging_Server_Adapter.h \
+ Reactor_Logging_Server_T.h \
+ SLDEX_export.h \
+ SLD_export.h \
+ Service_Reporter.h \
+ TPCLS_export.h \
+ TPC_Logging_Server.h \
+ TPLS_export.h \
+ TP_Logging_Server.h
+
+display_logfile_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+endif !BUILD_ACE_FOR_TAO
+
+## Makefile.C++NPv2_Reactor_Log_Server.am
+
+if !BUILD_ACE_FOR_TAO
+if !BUILD_USES_WCHAR
+noinst_PROGRAMS += reactor_logging_server
+
+reactor_logging_server_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+reactor_logging_server_SOURCES = \
+ Logging_Acceptor.cpp \
+ Logging_Event_Handler.cpp \
+ Logging_Event_Handler_Ex.cpp \
+ Logging_Handler.cpp \
+ Reactor_Logging_Server.cpp \
+ Logging_Acceptor.h \
+ Logging_Event_Handler.h \
+ Logging_Event_Handler_Ex.h \
+ Logging_Handler.h
+
+reactor_logging_server_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+endif !BUILD_USES_WCHAR
+endif !BUILD_ACE_FOR_TAO
+
+## Makefile.C++NPv2_SLD.am
+
+if !BUILD_ACE_FOR_TAO
+if !BUILD_USES_WCHAR
+
+noinst_LTLIBRARIES += libSLD.la
+
+libSLD_la_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR) \
+ -DSLD_BUILD_DLL
+
+libSLD_la_SOURCES = \
+ Logging_Acceptor.cpp \
+ Logging_Event_Handler.cpp \
+ Logging_Handler.cpp \
+ SLD.cpp
+
+noinst_HEADERS += \
+ Logging_Acceptor.h \
+ Logging_Event_Handler.h \
+ Logging_Handler.h \
+ Reactor_Logging_Server_T.cpp
+
+endif !BUILD_USES_WCHAR
+endif !BUILD_ACE_FOR_TAO
+
+## Makefile.C++NPv2_SLDex.am
+
+if !BUILD_ACE_FOR_TAO
+if !BUILD_USES_WCHAR
+
+noinst_LTLIBRARIES += libSLDex.la
+
+libSLDex_la_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR) \
+ -DSLDEX_BUILD_DLL
+
+libSLDex_la_SOURCES = \
+ Logging_Acceptor.cpp \
+ Logging_Event_Handler.cpp \
+ Logging_Event_Handler_Ex.cpp \
+ Logging_Handler.cpp \
+ Reactor_Logging_Server_Adapter.cpp \
+ SLDex.cpp \
+ Server_Shutdown.cpp
+
+noinst_HEADERS += \
+ Logging_Acceptor.h \
+ Logging_Event_Handler.h \
+ Logging_Event_Handler_Ex.h \
+ Logging_Handler.h \
+ Reactor_Logging_Server_Adapter.h \
+ Reactor_Logging_Server_T.cpp
+
+endif !BUILD_USES_WCHAR
+endif !BUILD_ACE_FOR_TAO
+
+## Makefile.C++NPv2_SR_Configurable_Log_Server.am
+noinst_PROGRAMS += sr_configurable_logging_server
+
+sr_configurable_logging_server_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+sr_configurable_logging_server_SOURCES = \
+ SR_Configurable_Logging_Server.cpp \
+ AC_CLD_export.h \
+ AC_Client_Logging_Daemon.h \
+ AIO_CLD_export.h \
+ AIO_Client_Logging_Daemon.h \
+ CLD_export.h \
+ Logging_Acceptor.h \
+ Logging_Acceptor_Ex.h \
+ Logging_Event_Handler.h \
+ Logging_Event_Handler_Ex.h \
+ Logging_Handler.h \
+ Reactor_Logging_Server_Adapter.h \
+ Reactor_Logging_Server_T.h \
+ SLDEX_export.h \
+ SLD_export.h \
+ Service_Reporter.h \
+ TPCLS_export.h \
+ TPC_Logging_Server.h \
+ TPLS_export.h \
+ TP_Logging_Server.h
+
+sr_configurable_logging_server_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Makefile.C++NPv2_Select_Reactor_Log_Server.am
+
+if !BUILD_ACE_FOR_TAO
+if !BUILD_USES_WCHAR
+noinst_PROGRAMS += select_reactor_logging_server
+
+select_reactor_logging_server_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+select_reactor_logging_server_SOURCES = \
+ Logging_Acceptor.cpp \
+ Logging_Event_Handler.cpp \
+ Logging_Event_Handler_Ex.cpp \
+ Logging_Handler.cpp \
+ Select_Reactor_Logging_Server.cpp \
+ Logging_Acceptor.h \
+ Logging_Event_Handler.h \
+ Logging_Event_Handler_Ex.h \
+ Logging_Handler.h
+
+select_reactor_logging_server_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+endif !BUILD_USES_WCHAR
+endif !BUILD_ACE_FOR_TAO
+
+## Makefile.C++NPv2_TPCLS.am
+
+if BUILD_SSL
+if !BUILD_ACE_FOR_TAO
+if !BUILD_USES_WCHAR
+
+noinst_LTLIBRARIES += libTPCLS.la
+
+libTPCLS_la_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR) \
+ -DACE_HAS_SSL=1 \
+ @ACE_TLS_CPPFLAGS@ \
+ -DTPCLS_BUILD_DLL
+
+libTPCLS_la_SOURCES = \
+ Logging_Handler.cpp \
+ TPC_Logging_Server.cpp
+
+libTPCLS_la_LDFLAGS = \
+ @ACE_TLS_LDFLAGS@
+
+noinst_HEADERS += \
+ Logging_Handler.h \
+ Reactor_Logging_Server_T.cpp \
+ TPC_Logging_Server.h
+
+endif !BUILD_USES_WCHAR
+endif !BUILD_ACE_FOR_TAO
+endif BUILD_SSL
+
+## Makefile.C++NPv2_TPLS.am
+
+if !BUILD_ACE_FOR_TAO
+if !BUILD_USES_WCHAR
+
+noinst_LTLIBRARIES += libTPLS.la
+
+libTPLS_la_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR) \
+ -DTPLS_BUILD_DLL
+
+libTPLS_la_SOURCES = \
+ Logging_Acceptor.cpp \
+ Logging_Event_Handler.cpp \
+ Logging_Handler.cpp \
+ TP_Logging_Server.cpp
+
+noinst_HEADERS += \
+ Logging_Acceptor.h \
+ Logging_Event_Handler.h \
+ Logging_Handler.h \
+ Reactor_Logging_Server_T.cpp \
+ TP_Logging_Server.h
+
+endif !BUILD_USES_WCHAR
+endif !BUILD_ACE_FOR_TAO
+
+## Makefile.C++NPv2_TP_Reactor_Log_Server.am
+
+if !BUILD_ACE_FOR_TAO
+if !BUILD_USES_WCHAR
+noinst_PROGRAMS += tp_reactor_logging_server
+
+tp_reactor_logging_server_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+tp_reactor_logging_server_SOURCES = \
+ Logging_Acceptor.cpp \
+ Logging_Event_Handler.cpp \
+ Logging_Event_Handler_Ex.cpp \
+ Logging_Handler.cpp \
+ TP_Reactor_Logging_Server.cpp \
+ Logging_Acceptor.h \
+ Logging_Event_Handler.h \
+ Logging_Event_Handler_Ex.h \
+ Logging_Handler.h
+
+tp_reactor_logging_server_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+endif !BUILD_USES_WCHAR
+endif !BUILD_ACE_FOR_TAO
+
+## Makefile.C++NPv2_WFMO_Reactor_Log_Server.am
+
+if BUILD_WFMO
+if !BUILD_ACE_FOR_TAO
+if !BUILD_USES_WCHAR
+noinst_PROGRAMS += wfmo_reactor_logging_server
+
+wfmo_reactor_logging_server_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+wfmo_reactor_logging_server_SOURCES = \
+ Logging_Acceptor.cpp \
+ Logging_Event_Handler.cpp \
+ Logging_Event_Handler_Ex.cpp \
+ Logging_Handler.cpp \
+ WFMO_Reactor_Logging_Server.cpp \
+ Logging_Acceptor.h \
+ Logging_Event_Handler.h \
+ Logging_Event_Handler_Ex.h \
+ Logging_Handler.h
+
+wfmo_reactor_logging_server_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+endif !BUILD_USES_WCHAR
+endif !BUILD_ACE_FOR_TAO
+endif BUILD_WFMO
+
+## Clean up template repositories, etc.
+clean-local:
+ -rm -f *~ *.bak *.rpo *.sym lib*.*_pure_* core core.*
+ -rm -f gcctemp.c gcctemp so_locations *.ics
+ -rm -rf cxx_repository ptrepository ti_files
+ -rm -rf templateregistry ir.out
+ -rm -rf ptrepository SunWS_cache Templates.DB
diff --git a/ACE/examples/C++NPv2/README b/ACE/examples/C++NPv2/README
new file mode 100644
index 00000000000..a2d8759dd80
--- /dev/null
+++ b/ACE/examples/C++NPv2/README
@@ -0,0 +1,99 @@
+(This is file $Id$)
+
+The files in this directory contain the source code from the book
+``C++ Network Programming: Systematic Reuse with ACE and Frameworks''
+(C++NPv2) by Douglas C. Schmidt and Stephen D. Huston (Addison-Wesley
+2001, ISBN 0-201-79525-6).
+
+We have compiled and run these files on the following platforms:
+
+ Sun Solaris 8 on SPARC using Sun Forte 6.
+ Redhat Linux 7.1 using g++ 2.96.
+ Microsoft Windows 2000 using Microsoft Visual C++ 6.
+
+You must have the ACE_ROOT environment variable set correctly to build
+these examples. ACE_ROOT must refer to the top-level ACE_wrappers
+directory. Please see $ACE_ROOT/ACE-INSTALL.html for instructions on
+how to build the ACE toolkit.
+
+Mapping Source Files to Book Chapters
+-------------------------------------
+
+The files in this directory map to the chapters in C++NPv2 as follows:
+
+Chapter 3 Logging_Acceptor.cpp
+ Logging_Acceptor.h
+ Logging_Acceptor_Ex.h
+ Logging_Event_Handler.cpp
+ Logging_Event_Handler.h
+ Logging_Event_Handler_Ex.cpp
+ Logging_Event_Handler_Ex.h
+ Logging_Handler.cpp
+ Logging_Handler.h
+ Reactor_Logging_Server.cpp
+ Reactor_Logging_Server_T.h
+ Reactor_Logging_Server_T.cpp
+
+Chapter 4 Select_Reactor_Logging_Server.cpp
+ TP_Reactor_Logging_Server.cpp
+ WFMO_Reactor_Logging_Server.cpp
+
+Chapter 5 Configurable_Logging_Server.cpp
+ Reactor_Logging_Server_Adapter.cpp
+ Reactor_Logging_Server_Adapter.h
+ Service_Reporter.cpp
+ Service_Reporter.h
+ Server_Shutdown.cpp
+ SLD.cpp
+ SLDEX_export.h
+ SLD_export.h
+ SLDex.cpp
+
+Chapter 6 Client_Logging_Daemon.cpp
+ CLD_export.h
+ TPLS_export.h
+ TP_Logging_Server.cpp
+ TP_Logging_Server.h
+
+Chapter 7 AC_CLD_export.h
+ AC_Client_Logging_Daemon.cpp
+ SR_Configurable_Logging_Server.cpp
+ TPC_Logging_Server.cpp
+ TPC_Logging_Server.h
+ TPCLS_export.h
+
+Chapter 8 AIO_CLD_export.h
+ AIO_Client_Logging_Daemon.cpp
+
+Chapter 9 display_logfile.cpp
+
+Microsoft Visual C++ users:
+---------------------------
+
+The examples.dsw file is a Microsoft Visual C++ workspace file that
+contains projects for the individual programs. You can either build
+them separately, or use the Batch Build command to build multiple
+projects at once.
+
+All other users:
+----------------
+
+Assuming that your system is configured correctly, you should be able
+to type
+
+% make
+
+to compile all of the programs, and
+
+% make clean
+
+to remove all the files that were generated during compilation.
+
+There are also individual Makefiles for each separate example program.
+These makefiles have a ".mak" suffix. For example, display_logfile.mak
+is the makefile for the display_logfile program.
+
+All of the files in these directories are copyright Addison Wesley,
+and they come with absolutely no warranty whatsoever. Permission is
+hereby granted to use these programs for educational or commercial
+purposes.
diff --git a/ACE/examples/C++NPv2/Reactor_Logging_Server.cpp b/ACE/examples/C++NPv2/Reactor_Logging_Server.cpp
new file mode 100644
index 00000000000..b36539c2a6d
--- /dev/null
+++ b/ACE/examples/C++NPv2/Reactor_Logging_Server.cpp
@@ -0,0 +1,29 @@
+/*
+** $Id$
+**
+** Copyright 2002 Addison Wesley. All Rights Reserved.
+*/
+
+#include "Reactor_Logging_Server_T.h"
+#include "Logging_Acceptor_Ex.h"
+#include "ace/Log_Msg.h"
+
+typedef Reactor_Logging_Server<Logging_Acceptor_Ex>
+ Server_Logging_Daemon;
+
+int main (int argc, char *argv[])
+{
+ ACE_Reactor reactor;
+ Server_Logging_Daemon *server;
+ // Ignore argv[0]...
+ --argc; ++argv;
+ ACE_NEW_RETURN (server,
+ Server_Logging_Daemon (argc, argv, &reactor),
+ 1);
+
+ if (reactor.run_reactor_event_loop () == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, "%p\n",
+ "run_reactor_event_loop()"), 1);
+ return 0;
+}
+
diff --git a/ACE/examples/C++NPv2/Reactor_Logging_Server_Adapter.cpp b/ACE/examples/C++NPv2/Reactor_Logging_Server_Adapter.cpp
new file mode 100644
index 00000000000..128ad5cabd3
--- /dev/null
+++ b/ACE/examples/C++NPv2/Reactor_Logging_Server_Adapter.cpp
@@ -0,0 +1,69 @@
+/*
+** $Id$
+**
+** Copyright 2002 Addison Wesley. All Rights Reserved.
+*/
+
+#ifndef _REACTOR_LOGGING_SERVER_ADAPTER_C
+#define _REACTOR_LOGGING_SERVER_ADAPTER_C
+
+#include "ace/ACE.h"
+#include "ace/Auto_Ptr.h"
+#include "ace/INET_Addr.h"
+#include "Reactor_Logging_Server_Adapter.h"
+#include "ace/OS_NS_string.h"
+#include "ace/OS_NS_stdio.h"
+
+template <class ACCEPTOR> int
+Reactor_Logging_Server_Adapter<ACCEPTOR>::init (int argc,
+ ACE_TCHAR *argv[]) {
+ int i;
+ char **array = 0;
+ ACE_NEW_RETURN (array, char*[argc], -1);
+ ACE_Auto_Array_Ptr<char *> char_argv (array);
+
+ for (i = 0; i < argc; ++i)
+ char_argv[i] = ACE::strnew (ACE_TEXT_ALWAYS_CHAR (argv[i]));
+ ACE_NEW_NORETURN (server_, Reactor_Logging_Server<ACCEPTOR>
+ (i, char_argv.get (),
+ ACE_Reactor::instance ()));
+ for (i = 0; i < argc; ++i) ACE::strdelete (char_argv[i]);
+ return server_ == 0 ? -1 : 0;
+}
+
+
+template <class ACCEPTOR> int
+Reactor_Logging_Server_Adapter<ACCEPTOR>::fini ()
+{ server_->handle_close (); server_ = 0; return 0; }
+
+
+template <class ACCEPTOR> int
+Reactor_Logging_Server_Adapter<ACCEPTOR>::info
+ (ACE_TCHAR **bufferp, size_t length) const {
+ ACE_INET_Addr local_addr;
+ server_->acceptor ().get_local_addr (local_addr);
+
+ ACE_TCHAR buf[BUFSIZ];
+ ACE_OS::sprintf (buf,
+ ACE_TEXT ("%hu"),
+ local_addr.get_port_number ());
+ ACE_OS::strcat
+ (buf, ACE_TEXT ("/tcp # Reactor-based logging server\n"));
+ if (*bufferp == 0)
+ *bufferp = ACE::strnew (buf);
+ else
+ ACE_OS::strncpy (*bufferp, buf, length);
+ return ACE_OS::strlen (*bufferp);
+}
+
+
+template <class ACCEPTOR> int
+Reactor_Logging_Server_Adapter<ACCEPTOR>::suspend ()
+{ return server_->reactor ()->suspend_handler (server_); }
+
+
+template <class ACCEPTOR> int
+Reactor_Logging_Server_Adapter<ACCEPTOR>::resume ()
+{ return server_->reactor ()->resume_handler (server_); }
+
+#endif /* _REACTOR_LOGGING_SERVER_ADAPTER_C */
diff --git a/ACE/examples/C++NPv2/Reactor_Logging_Server_Adapter.h b/ACE/examples/C++NPv2/Reactor_Logging_Server_Adapter.h
new file mode 100644
index 00000000000..aeda81205ab
--- /dev/null
+++ b/ACE/examples/C++NPv2/Reactor_Logging_Server_Adapter.h
@@ -0,0 +1,35 @@
+/*
+** $Id$
+**
+** Copyright 2002 Addison Wesley. All Rights Reserved.
+*/
+
+#ifndef _REACTOR_LOGGING_SERVER_ADAPTER_H
+#define _REACTOR_LOGGING_SERVER_ADAPTER_H
+
+#include "ace/Service_Object.h"
+#include "Reactor_Logging_Server_T.h"
+
+template <class ACCEPTOR>
+class Reactor_Logging_Server_Adapter : public ACE_Service_Object {
+public:
+ // Hook methods inherited from <ACE_Service_Object>.
+ virtual int init (int argc, ACE_TCHAR *argv[]);
+ virtual int fini ();
+ virtual int info (ACE_TCHAR **, size_t) const;
+ virtual int suspend ();
+ virtual int resume ();
+
+private:
+ Reactor_Logging_Server<ACCEPTOR> *server_;
+};
+
+#if defined (ACE_TEMPLATES_REQUIRE_SOURCE)
+#include "Reactor_Logging_Server_Adapter.cpp"
+#endif /* ACE_TEMPLATES_REQUIRE_SOURCE */
+
+#if defined (ACE_TEMPLATES_REQUIRE_PRAGMA)
+#pragma implementation ("Reactor_Logging_Server_Adapter.cpp")
+#endif /* ACE_TEMPLATES_REQUIRE_PRAGMA */
+
+#endif /* _REACTOR_LOGGING_SERVER_ADAPTER_H */
diff --git a/ACE/examples/C++NPv2/Reactor_Logging_Server_T.cpp b/ACE/examples/C++NPv2/Reactor_Logging_Server_T.cpp
new file mode 100644
index 00000000000..3e25be39373
--- /dev/null
+++ b/ACE/examples/C++NPv2/Reactor_Logging_Server_T.cpp
@@ -0,0 +1,26 @@
+/*
+** $Id$
+**
+** Copyright 2002 Addison Wesley. All Rights Reserved.
+*/
+
+// Implementations for Reactor_Logging_Server<>
+
+template <class ACCEPTOR>
+Reactor_Logging_Server<ACCEPTOR>::Reactor_Logging_Server
+ (int argc, char *argv[], ACE_Reactor *reactor)
+ : ACCEPTOR (reactor) {
+ u_short logger_port = argc > 0 ? atoi (argv[0]) : 0;
+ ACE_TYPENAME ACCEPTOR::PEER_ADDR server_addr;
+ int result;
+
+ if (logger_port != 0)
+ result = server_addr.set (logger_port,
+ (ACE_UINT32) INADDR_ANY);
+ else
+ result = server_addr.set ("ace_logger",
+ (ACE_UINT32) INADDR_ANY);
+ if (result != -1)
+ result = ACCEPTOR::open (server_addr);
+ if (result == -1) reactor->end_reactor_event_loop ();
+}
diff --git a/ACE/examples/C++NPv2/Reactor_Logging_Server_T.h b/ACE/examples/C++NPv2/Reactor_Logging_Server_T.h
new file mode 100644
index 00000000000..ee16f8a061e
--- /dev/null
+++ b/ACE/examples/C++NPv2/Reactor_Logging_Server_T.h
@@ -0,0 +1,29 @@
+/*
+** $Id$
+**
+** Copyright 2002 Addison Wesley. All Rights Reserved.
+*/
+
+#ifndef _REACTOR_LOGGING_SERVER_T_H
+#define _REACTOR_LOGGING_SERVER_T_H
+
+#include "ace/ACE.h"
+#include "ace/Reactor.h"
+
+template <class ACCEPTOR>
+class Reactor_Logging_Server : public ACCEPTOR
+{
+public:
+ Reactor_Logging_Server (int argc, char *argv[],
+ ACE_Reactor *reactor);
+};
+
+#if defined (ACE_TEMPLATES_REQUIRE_SOURCE)
+#include "Reactor_Logging_Server_T.cpp"
+#endif /* ACE_TEMPLATES_REQUIRE_SOURCE */
+
+#if defined (ACE_TEMPLATES_REQUIRE_PRAGMA)
+#pragma implementation ("Reactor_Logging_Server_T.cpp")
+#endif /* ACE_TEMPLATES_REQUIRE_PRAGMA */
+
+#endif /* _REACTOR_LOGGING_SERVER_T_H */
diff --git a/ACE/examples/C++NPv2/SLD.cpp b/ACE/examples/C++NPv2/SLD.cpp
new file mode 100644
index 00000000000..3aef89d0df6
--- /dev/null
+++ b/ACE/examples/C++NPv2/SLD.cpp
@@ -0,0 +1,17 @@
+/*
+** $Id$
+**
+** Copyright 2002 Addison Wesley. All Rights Reserved.
+*/
+
+#include "ace/Log_Msg.h"
+
+#include "Reactor_Logging_Server_Adapter.h"
+#include "Logging_Acceptor.h"
+#include "SLD_export.h"
+
+typedef Reactor_Logging_Server_Adapter<Logging_Acceptor>
+ Server_Logging_Daemon;
+
+ACE_FACTORY_DEFINE (SLD, Server_Logging_Daemon)
+
diff --git a/ACE/examples/C++NPv2/SLDEX_export.h b/ACE/examples/C++NPv2/SLDEX_export.h
new file mode 100644
index 00000000000..b6cfca66b04
--- /dev/null
+++ b/ACE/examples/C++NPv2/SLDEX_export.h
@@ -0,0 +1,38 @@
+
+// -*- C++ -*-
+// $Id$
+// Definition for Win32 Export directives.
+// This file is generated automatically by generate_export_file.pl SLDEX
+// ------------------------------
+#ifndef SLDEX_EXPORT_H
+#define SLDEX_EXPORT_H
+
+#include "ace/config-all.h"
+
+#if defined (ACE_AS_STATIC_LIBS) && !defined (SLDEX_HAS_DLL)
+# define SLDEX_HAS_DLL 0
+#endif /* ACE_AS_STATIC_LIBS && ! SLDEX_HAS_DLL */
+
+#if !defined (SLDEX_HAS_DLL)
+# define SLDEX_HAS_DLL 1
+#endif /* ! SLDEX_HAS_DLL */
+
+#if defined (SLDEX_HAS_DLL) && (SLDEX_HAS_DLL == 1)
+# if defined (SLDEX_BUILD_DLL)
+# define SLDEX_Export ACE_Proper_Export_Flag
+# define SLDEX_SINGLETON_DECLARATION(T) ACE_EXPORT_SINGLETON_DECLARATION (T)
+# define SLDEX_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) ACE_EXPORT_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK)
+# else /* SLDEX_BUILD_DLL */
+# define SLDEX_Export ACE_Proper_Import_Flag
+# define SLDEX_SINGLETON_DECLARATION(T) ACE_IMPORT_SINGLETON_DECLARATION (T)
+# define SLDEX_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) ACE_IMPORT_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK)
+# endif /* SLDEX_BUILD_DLL */
+#else /* SLDEX_HAS_DLL == 1 */
+# define SLDEX_Export
+# define SLDEX_SINGLETON_DECLARATION(T)
+# define SLDEX_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK)
+#endif /* SLDEX_HAS_DLL == 1 */
+
+#endif /* SLDEX_EXPORT_H */
+
+// End of auto generated file.
diff --git a/ACE/examples/C++NPv2/SLD_export.h b/ACE/examples/C++NPv2/SLD_export.h
new file mode 100644
index 00000000000..77f7467b43a
--- /dev/null
+++ b/ACE/examples/C++NPv2/SLD_export.h
@@ -0,0 +1,38 @@
+
+// -*- C++ -*-
+// $Id$
+// Definition for Win32 Export directives.
+// This file is generated automatically by generate_export_file.pl SLD
+// ------------------------------
+#ifndef SLD_EXPORT_H
+#define SLD_EXPORT_H
+
+#include "ace/config-all.h"
+
+#if defined (ACE_AS_STATIC_LIBS) && !defined (SLD_HAS_DLL)
+# define SLD_HAS_DLL 0
+#endif /* ACE_AS_STATIC_LIBS && ! SLD_HAS_DLL */
+
+#if !defined (SLD_HAS_DLL)
+# define SLD_HAS_DLL 1
+#endif /* ! SLD_HAS_DLL */
+
+#if defined (SLD_HAS_DLL) && (SLD_HAS_DLL == 1)
+# if defined (SLD_BUILD_DLL)
+# define SLD_Export ACE_Proper_Export_Flag
+# define SLD_SINGLETON_DECLARATION(T) ACE_EXPORT_SINGLETON_DECLARATION (T)
+# define SLD_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) ACE_EXPORT_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK)
+# else /* SLD_BUILD_DLL */
+# define SLD_Export ACE_Proper_Import_Flag
+# define SLD_SINGLETON_DECLARATION(T) ACE_IMPORT_SINGLETON_DECLARATION (T)
+# define SLD_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) ACE_IMPORT_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK)
+# endif /* SLD_BUILD_DLL */
+#else /* SLD_HAS_DLL == 1 */
+# define SLD_Export
+# define SLD_SINGLETON_DECLARATION(T)
+# define SLD_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK)
+#endif /* SLD_HAS_DLL == 1 */
+
+#endif /* SLD_EXPORT_H */
+
+// End of auto generated file.
diff --git a/ACE/examples/C++NPv2/SLDex.cpp b/ACE/examples/C++NPv2/SLDex.cpp
new file mode 100644
index 00000000000..fbaf7cb3111
--- /dev/null
+++ b/ACE/examples/C++NPv2/SLDex.cpp
@@ -0,0 +1,17 @@
+/*
+** $Id$
+**
+** Copyright 2002 Addison Wesley. All Rights Reserved.
+*/
+
+#include "ace/Log_Msg.h"
+
+#include "Reactor_Logging_Server_Adapter.h"
+#include "Logging_Acceptor_Ex.h"
+#include "SLDEX_export.h"
+
+typedef Reactor_Logging_Server_Adapter<Logging_Acceptor_Ex>
+ Server_Logging_Daemon_Ex;
+
+ACE_FACTORY_DEFINE (SLDEX, Server_Logging_Daemon_Ex)
+
diff --git a/ACE/examples/C++NPv2/SR_Configurable_Logging_Server.cpp b/ACE/examples/C++NPv2/SR_Configurable_Logging_Server.cpp
new file mode 100644
index 00000000000..97fc65d386e
--- /dev/null
+++ b/ACE/examples/C++NPv2/SR_Configurable_Logging_Server.cpp
@@ -0,0 +1,26 @@
+/*
+** $Id$
+**
+** Copyright 2002 Addison Wesley. All Rights Reserved.
+*/
+
+#include "ace/OS_main.h"
+#include "ace/OS_Memory.h"
+#include "ace/Reactor.h"
+#include "ace/Select_Reactor.h"
+#include "ace/Service_Config.h"
+
+
+int ACE_TMAIN (int argc, ACE_TCHAR *argv[]) {
+ ACE_Select_Reactor *select_reactor;
+ ACE_NEW_RETURN (select_reactor, ACE_Select_Reactor, 1);
+ ACE_Reactor *reactor;
+ ACE_NEW_RETURN (reactor, ACE_Reactor (select_reactor, 1), 1);
+ ACE_Reactor::close_singleton ();
+ ACE_Reactor::instance (reactor, 1);
+
+ ACE_Service_Config::open (argc, argv);
+
+ ACE_Reactor::instance ()->run_reactor_event_loop ();
+ return 0;
+}
diff --git a/ACE/examples/C++NPv2/Select_Reactor_Logging_Server.cpp b/ACE/examples/C++NPv2/Select_Reactor_Logging_Server.cpp
new file mode 100644
index 00000000000..24123c3b3c6
--- /dev/null
+++ b/ACE/examples/C++NPv2/Select_Reactor_Logging_Server.cpp
@@ -0,0 +1,105 @@
+/*
+** $Id$
+**
+** Copyright 2002 Addison Wesley. All Rights Reserved.
+*/
+
+// FUZZ: disable check_for_streams_include
+#include "ace/streams.h"
+
+#include "ace/Reactor.h"
+#include "ace/Select_Reactor.h"
+#include "ace/Thread_Manager.h"
+
+#if defined (ACE_WIN32) && (!defined (ACE_HAS_STANDARD_CPP_LIBRARY) || \
+ (ACE_HAS_STANDARD_CPP_LIBRARY == 0) || \
+ defined (ACE_USES_OLD_IOSTREAMS))
+# include <stdio.h>
+#else
+# include <string>
+#endif
+
+#include "Reactor_Logging_Server_T.h"
+#include "Logging_Acceptor_Ex.h"
+
+typedef Reactor_Logging_Server<Logging_Acceptor_Ex>
+ Server_Logging_Daemon;
+
+
+class Quit_Handler : public ACE_Event_Handler {
+ friend class ace_dewarn_gplusplus;
+public:
+ Quit_Handler (ACE_Reactor *r) : ACE_Event_Handler (r) {}
+
+ virtual int handle_exception (ACE_HANDLE) {
+ reactor ()->end_reactor_event_loop ();
+ return -1; // Trigger call to handle_close() method.
+ }
+
+ virtual int handle_close (ACE_HANDLE, ACE_Reactor_Mask)
+ { delete this; return 0; }
+
+private:
+
+ // Private destructor ensures dynamic allocation.
+ virtual ~Quit_Handler () {}
+};
+
+
+static ACE_THR_FUNC_RETURN event_loop (void *arg) {
+ ACE_Reactor *reactor = static_cast<ACE_Reactor *> (arg);
+
+ reactor->owner (ACE_OS::thr_self ());
+ reactor->run_reactor_event_loop ();
+ return 0;
+}
+
+
+static ACE_THR_FUNC_RETURN controller (void *arg) {
+ ACE_Reactor *reactor = static_cast<ACE_Reactor *> (arg);
+
+ Quit_Handler *quit_handler = 0;
+ ACE_NEW_RETURN (quit_handler, Quit_Handler (reactor), 0);
+
+#if defined (ACE_WIN32) && (!defined (ACE_HAS_STANDARD_CPP_LIBRARY) || \
+ (ACE_HAS_STANDARD_CPP_LIBRARY == 0) || \
+ defined (ACE_USES_OLD_IOSTREAMS))
+ for (;;) {
+ char user_input[80];
+ fgets (user_input, sizeof (user_input), stdin);
+ if (ACE_OS::strcmp (user_input, "quit") == 0) {
+ reactor->notify (quit_handler);
+ break;
+ }
+ }
+#else
+ for (;;) {
+ std::string user_input;
+ std::getline (cin, user_input, '\n');
+ if (user_input == "quit") {
+ reactor->notify (quit_handler);
+ break;
+ }
+ }
+#endif
+
+ return 0;
+}
+
+
+int main (int argc, char *argv[])
+{
+ ACE_Select_Reactor select_reactor;
+ ACE_Reactor reactor (&select_reactor);
+
+ Server_Logging_Daemon *server;
+ // Ignore argv[0]...
+ --argc; ++argv;
+ ACE_NEW_RETURN (server,
+ Server_Logging_Daemon (argc, argv, &reactor),
+ 1);
+ ACE_Thread_Manager::instance ()->spawn (event_loop, &reactor);
+ ACE_Thread_Manager::instance ()->spawn (controller, &reactor);
+ return ACE_Thread_Manager::instance ()->wait ();
+}
+
diff --git a/ACE/examples/C++NPv2/Server_Shutdown.cpp b/ACE/examples/C++NPv2/Server_Shutdown.cpp
new file mode 100644
index 00000000000..f0d6df0cdfd
--- /dev/null
+++ b/ACE/examples/C++NPv2/Server_Shutdown.cpp
@@ -0,0 +1,98 @@
+/*
+** $Id$
+**
+** Copyright 2002 Addison Wesley. All Rights Reserved.
+*/
+
+#include "ace/Event_Handler.h"
+#include "ace/Reactor.h"
+#include "ace/Service_Object.h"
+#include "ace/Thread_Manager.h"
+#include "ace/OS_NS_string.h"
+
+// FUZZ: disable check_for_streams_include
+#include "ace/streams.h"
+
+#if defined (ACE_WIN32) && (!defined (ACE_HAS_STANDARD_CPP_LIBRARY) || \
+ (ACE_HAS_STANDARD_CPP_LIBRARY == 0) || \
+ defined (ACE_USES_OLD_IOSTREAMS))
+# include <stdio.h>
+#else
+# include <string>
+#endif
+
+#include "SLDEX_export.h"
+
+
+class Quit_Handler : public ACE_Event_Handler {
+ friend class ace_dewarn_gplusplus;
+public:
+ Quit_Handler (ACE_Reactor *r) : ACE_Event_Handler (r) {}
+
+ virtual int handle_exception (ACE_HANDLE) {
+ reactor ()->end_reactor_event_loop ();
+ return -1; // Trigger call to handle_close() method.
+ }
+
+ virtual int handle_close (ACE_HANDLE, ACE_Reactor_Mask)
+ { delete this; return 0; }
+
+private:
+
+ // Private destructor ensures dynamic allocation.
+ virtual ~Quit_Handler () {}
+};
+
+
+static ACE_THR_FUNC_RETURN controller (void *arg) {
+ ACE_Reactor *reactor = static_cast<ACE_Reactor *> (arg);
+
+ Quit_Handler *quit_handler = 0;
+ ACE_NEW_RETURN (quit_handler, Quit_Handler (reactor), 0);
+
+#if defined (ACE_WIN32) && (!defined (ACE_HAS_STANDARD_CPP_LIBRARY) || \
+ (ACE_HAS_STANDARD_CPP_LIBRARY == 0) || \
+ defined (ACE_USES_OLD_IOSTREAMS))
+ for (;;) {
+ char user_input[80];
+ fgets (user_input, sizeof (user_input), stdin);
+ if (ACE_OS::strcmp (user_input, "quit") == 0) {
+ reactor->notify (quit_handler);
+ break;
+ }
+ }
+#else
+ for (;;) {
+ std::string user_input;
+ std::getline (cin, user_input, '\n');
+ if (user_input == "quit") {
+ reactor->notify (quit_handler);
+ break;
+ }
+ }
+#endif
+
+ return 0;
+}
+
+
+class Server_Shutdown : public ACE_Service_Object {
+public:
+ virtual int init (int, ACE_TCHAR *[]) {
+ reactor_ = ACE_Reactor::instance ();
+ return ACE_Thread_Manager::instance ()->spawn
+ (controller, reactor_, THR_DETACHED);
+ }
+
+ virtual int fini () {
+ Quit_Handler *quit_handler = 0;
+ ACE_NEW_RETURN (quit_handler,
+ Quit_Handler (reactor_), -1);
+ return reactor_->notify (quit_handler);
+ }
+
+private:
+ ACE_Reactor *reactor_;
+};
+
+ACE_FACTORY_DEFINE (SLDEX, Server_Shutdown)
diff --git a/ACE/examples/C++NPv2/Service_Reporter.cpp b/ACE/examples/C++NPv2/Service_Reporter.cpp
new file mode 100644
index 00000000000..ad9cd05d26c
--- /dev/null
+++ b/ACE/examples/C++NPv2/Service_Reporter.cpp
@@ -0,0 +1,125 @@
+/*
+** $Id$
+**
+** Copyright 2002 Addison Wesley. All Rights Reserved.
+*/
+
+#include "ace/OS_NS_stdio.h"
+#include "ace/OS_NS_string.h"
+#include "ace/Get_Opt.h"
+#include "ace/INET_Addr.h"
+#include "ace/Log_Msg.h"
+#include "ace/Service_Config.h"
+#include "ace/Service_Repository.h"
+#include "ace/Service_Types.h"
+#include "ace/SOCK_Stream.h"
+#include "Service_Reporter.h"
+
+
+int Service_Reporter::init (int argc, ACE_TCHAR *argv[]) {
+ ACE_INET_Addr local_addr (Service_Reporter::DEFAULT_PORT);
+
+ // Start at argv[0].
+ ACE_Get_Opt get_opt (argc, argv, ACE_TEXT ("p:"), 0);
+ get_opt.long_option (ACE_TEXT ("port"),
+ 'p',
+ ACE_Get_Opt::ARG_REQUIRED);
+
+ for (int c; (c = get_opt ()) != -1; )
+ switch (c) {
+ case 'p':
+ local_addr.set_port_number
+ (ACE_OS::atoi (get_opt.opt_arg ()));
+ }
+
+ acceptor_.open (local_addr);
+ return reactor ()->register_handler
+ (this,
+ ACE_Event_Handler::ACCEPT_MASK);
+}
+
+
+int Service_Reporter::handle_input (ACE_HANDLE) {
+ ACE_SOCK_Stream peer_stream;
+ acceptor_.accept (peer_stream);
+
+ ACE_Service_Repository_Iterator iterator
+ (*ACE_Service_Repository::instance (), 0);
+
+ for (const ACE_Service_Type *st;
+ iterator.next (st) != 0;
+ iterator.advance ()) {
+ iovec iov[3];
+ iov[0].iov_base = const_cast<ACE_TCHAR *> (st->name ());
+ iov[0].iov_len =
+ ACE_OS::strlen (st->name ()) * sizeof (ACE_TCHAR);
+ const ACE_TCHAR *state = st->active () ?
+ ACE_TEXT (" (active) ") : ACE_TEXT (" (paused) ");
+ iov[1].iov_base = const_cast<ACE_TCHAR *> (state);
+ iov[1].iov_len =
+ ACE_OS::strlen (state) * sizeof (ACE_TCHAR);
+ ACE_TCHAR *report = 0; // Ask info() to allocate buffer
+ int len = st->type ()->info (&report, 0);
+ iov[2].iov_base = static_cast<ACE_TCHAR *> (report);
+ iov[2].iov_len = static_cast<size_t> (len);
+ iov[2].iov_len *= sizeof (ACE_TCHAR);
+ peer_stream.sendv_n (iov, 3);
+ ACE::strdelete (report);
+ }
+
+ peer_stream.close ();
+ return 0;
+}
+
+
+int Service_Reporter::info (ACE_TCHAR **bufferp,
+ size_t length) const {
+ ACE_INET_Addr local_addr;
+ acceptor_.get_local_addr (local_addr);
+
+ ACE_TCHAR buf[BUFSIZ];
+ ACE_OS::sprintf
+ (buf, ACE_TEXT ("%hu"), local_addr.get_port_number ());
+ ACE_OS::strcat
+ (buf, ACE_TEXT ("/tcp # lists services in daemon\n"));
+ if (*bufferp == 0)
+ *bufferp = ACE::strnew (buf);
+ else
+ ACE_OS::strncpy (*bufferp, buf, length);
+ return ACE_OS::strlen (*bufferp);
+}
+
+
+int Service_Reporter::suspend ()
+{ return reactor ()->suspend_handler (this); }
+
+int Service_Reporter::resume ()
+{ return reactor ()->resume_handler (this); }
+
+
+int Service_Reporter::fini () {
+ reactor ()->remove_handler
+ (this,
+ ACE_Event_Handler::ACCEPT_MASK
+ | ACE_Event_Handler::DONT_CALL);
+ return acceptor_.close ();
+}
+
+// Define the service object make and gobble functions.
+ACE_FACTORY_DEFINE (ACE_Local_Service, Service_Reporter)
+
+// Define the ACE_Static_Svc_Descriptor that conveys the service information
+// to the ACE_Service_Config.
+ACE_STATIC_SVC_DEFINE (
+ Reporter_Descriptor,
+ ACE_TEXT ("Service_Reporter"),
+ ACE_SVC_OBJ_T,
+ &ACE_SVC_NAME (Service_Reporter),
+ ACE_Service_Type::DELETE_THIS
+ | ACE_Service_Type::DELETE_OBJ,
+ 0 // This object is not initially active.
+)
+
+// Define the class that will register this service with ACE_Service_Config
+// at program startup.
+ACE_STATIC_SVC_REQUIRE (Reporter_Descriptor)
diff --git a/ACE/examples/C++NPv2/Service_Reporter.h b/ACE/examples/C++NPv2/Service_Reporter.h
new file mode 100644
index 00000000000..c6de7484767
--- /dev/null
+++ b/ACE/examples/C++NPv2/Service_Reporter.h
@@ -0,0 +1,38 @@
+/*
+** $Id$
+**
+** Copyright 2002 Addison Wesley. All Rights Reserved.
+*/
+
+#ifndef _SERVICE_REPORTER_H
+#define _SERVICE_REPORTER_H
+
+#include "ace/Reactor.h"
+#include "ace/Service_Object.h"
+#include "ace/SOCK_Acceptor.h"
+
+
+class Service_Reporter : public ACE_Service_Object {
+public:
+ Service_Reporter (ACE_Reactor *r = ACE_Reactor::instance ())
+ : ACE_Service_Object (r) {}
+
+protected:
+ // Hook methods inherited from <ACE_Service_Object>.
+ virtual int init (int argc, ACE_TCHAR *argv[]);
+ virtual int fini ();
+ virtual int info (ACE_TCHAR **, size_t) const;
+ virtual int suspend ();
+ virtual int resume ();
+
+ // Reactor hook methods.
+ virtual int handle_input (ACE_HANDLE);
+ virtual ACE_HANDLE get_handle () const
+ { return acceptor_.get_handle (); }
+
+private:
+ ACE_SOCK_Acceptor acceptor_; // Acceptor instance.
+ enum { DEFAULT_PORT = 9411 };
+};
+
+#endif /* _SERVICE_REPORTER_H */
diff --git a/ACE/examples/C++NPv2/TPCLS_export.h b/ACE/examples/C++NPv2/TPCLS_export.h
new file mode 100644
index 00000000000..b550ef28a95
--- /dev/null
+++ b/ACE/examples/C++NPv2/TPCLS_export.h
@@ -0,0 +1,54 @@
+
+// -*- C++ -*-
+// $Id$
+// Definition for Win32 Export directives.
+// This file is generated automatically by generate_export_file.pl TPCLS
+// ------------------------------
+#ifndef TPCLS_EXPORT_H
+#define TPCLS_EXPORT_H
+
+#include "ace/config-all.h"
+
+#if defined (ACE_AS_STATIC_LIBS) && !defined (TPCLS_HAS_DLL)
+# define TPCLS_HAS_DLL 0
+#endif /* ACE_AS_STATIC_LIBS && ! TPCLS_HAS_DLL */
+
+#if !defined (TPCLS_HAS_DLL)
+# define TPCLS_HAS_DLL 1
+#endif /* ! TPCLS_HAS_DLL */
+
+#if defined (TPCLS_HAS_DLL) && (TPCLS_HAS_DLL == 1)
+# if defined (TPCLS_BUILD_DLL)
+# define TPCLS_Export ACE_Proper_Export_Flag
+# define TPCLS_SINGLETON_DECLARATION(T) ACE_EXPORT_SINGLETON_DECLARATION (T)
+# define TPCLS_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) ACE_EXPORT_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK)
+# else /* TPCLS_BUILD_DLL */
+# define TPCLS_Export ACE_Proper_Import_Flag
+# define TPCLS_SINGLETON_DECLARATION(T) ACE_IMPORT_SINGLETON_DECLARATION (T)
+# define TPCLS_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) ACE_IMPORT_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK)
+# endif /* TPCLS_BUILD_DLL */
+#else /* TPCLS_HAS_DLL == 1 */
+# define TPCLS_Export
+# define TPCLS_SINGLETON_DECLARATION(T)
+# define TPCLS_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK)
+#endif /* TPCLS_HAS_DLL == 1 */
+
+// Set TPCLS_NTRACE = 0 to turn on library specific tracing even if
+// tracing is turned off for ACE.
+#if !defined (TPCLS_NTRACE)
+# if (ACE_NTRACE == 1)
+# define TPCLS_NTRACE 1
+# else /* (ACE_NTRACE == 1) */
+# define TPCLS_NTRACE 0
+# endif /* (ACE_NTRACE == 1) */
+#endif /* !TPCLS_NTRACE */
+
+#if (TPCLS_NTRACE == 1)
+# define TPCLS_TRACE(X)
+#else /* (TPCLS_NTRACE == 1) */
+# define TPCLS_TRACE(X) ACE_TRACE_IMPL(X)
+#endif /* (TPCLS_NTRACE == 1) */
+
+#endif /* TPCLS_EXPORT_H */
+
+// End of auto generated file.
diff --git a/ACE/examples/C++NPv2/TPC_Logging_Server.cpp b/ACE/examples/C++NPv2/TPC_Logging_Server.cpp
new file mode 100644
index 00000000000..b6ce76e1d40
--- /dev/null
+++ b/ACE/examples/C++NPv2/TPC_Logging_Server.cpp
@@ -0,0 +1,106 @@
+/*
+** $Id$
+**
+** This is the Thread-per-connection logging server example from Chapter 7.
+**
+** Copyright 2002 Addison Wesley. All Rights Reserved.
+*/
+
+#include "ace/OS_NS_string.h"
+#include "ace/FILE_Addr.h"
+#include "ace/FILE_Connector.h"
+#include "ace/os_include/os_netdb.h"
+#include "Reactor_Logging_Server_Adapter.h"
+#include "TPC_Logging_Server.h"
+#include "TPCLS_export.h"
+
+int TPC_Logging_Handler::open (void *) {
+ static const ACE_TCHAR LOGFILE_SUFFIX[] = ACE_TEXT (".log");
+ ACE_TCHAR filename[MAXHOSTNAMELEN + sizeof (LOGFILE_SUFFIX)];
+ ACE_INET_Addr logging_peer_addr;
+
+ peer ().get_remote_addr (logging_peer_addr);
+ logging_peer_addr.get_host_name (filename, MAXHOSTNAMELEN);
+ ACE_OS::strcat (filename, LOGFILE_SUFFIX);
+
+ ACE_FILE_Connector connector;
+ connector.connect (log_file_,
+ ACE_FILE_Addr (filename),
+ 0, // No timeout.
+ ACE_Addr::sap_any, // Ignored.
+ 0, // Don't try to reuse the addr.
+ O_RDWR | O_CREAT | O_APPEND,
+ ACE_DEFAULT_FILE_PERMS);
+
+ logging_handler_.peer ().set_handle (peer ().get_handle ());
+
+ return activate (THR_NEW_LWP | THR_DETACHED);
+}
+
+
+#if !defined (TPC_CERTIFICATE_FILENAME)
+# define TPC_CERTIFICATE_FILENAME "tpc-cert.pem"
+#endif /* !TPC_CERTIFICATE_FILENAME */
+#if !defined (TPC_KEY_FILENAME)
+# define TPC_KEY_FILENAME "tpc-key.pem"
+#endif /* !TPC_KEY_FILENAME */
+
+int TPC_Logging_Acceptor::open
+ (const ACE_SOCK_Acceptor::PEER_ADDR &local_addr,
+ ACE_Reactor *reactor,
+ int flags, int use_select, int reuse_addr) {
+ if (PARENT::open (local_addr, reactor, flags,
+ use_select, reuse_addr) != 0)
+ return -1;
+ OpenSSL_add_ssl_algorithms ();
+ ssl_ctx_ = SSL_CTX_new (SSLv3_server_method ());
+ if (ssl_ctx_ == 0) return -1;
+
+ if (SSL_CTX_use_certificate_file (ssl_ctx_,
+ TPC_CERTIFICATE_FILENAME,
+ SSL_FILETYPE_PEM) <= 0
+ || SSL_CTX_use_PrivateKey_file (ssl_ctx_,
+ TPC_KEY_FILENAME,
+ SSL_FILETYPE_PEM) <= 0
+ || !SSL_CTX_check_private_key (ssl_ctx_))
+ return -1;
+ ssl_ = SSL_new (ssl_ctx_);
+ return ssl_ == 0 ? -1 : 0;
+}
+
+
+int TPC_Logging_Acceptor::handle_close (ACE_HANDLE h,
+ ACE_Reactor_Mask mask) {
+ PARENT::handle_close (h, mask);
+ delete this;
+ return 0;
+}
+
+
+int TPC_Logging_Acceptor::accept_svc_handler
+ (TPC_Logging_Handler *sh) {
+ if (PARENT::accept_svc_handler (sh) == -1) return -1;
+ SSL_clear (ssl_); // Reset for new SSL connection.
+#if defined (ACE_WIN32)
+ // ACE_WIN32 is the only platform where ACE_HANDLE is not an int.
+ // See ace/config-lite.h for the typedefs.
+ SSL_set_fd (ssl_, reinterpret_cast<int> (sh->get_handle ()));
+#else
+ SSL_set_fd (ssl_, sh->get_handle ());
+#endif /* ACE_WIN32 */
+
+ SSL_set_verify
+ (ssl_,
+ SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
+ 0);
+ if (SSL_accept (ssl_) == -1
+ || SSL_shutdown (ssl_) == -1) return -1;
+ return 0;
+}
+
+
+typedef Reactor_Logging_Server_Adapter<TPC_Logging_Acceptor>
+ TPC_Logging_Server;
+
+ACE_FACTORY_DEFINE (TPCLS, TPC_Logging_Server)
+
diff --git a/ACE/examples/C++NPv2/TPC_Logging_Server.h b/ACE/examples/C++NPv2/TPC_Logging_Server.h
new file mode 100644
index 00000000000..2617c3b95ec
--- /dev/null
+++ b/ACE/examples/C++NPv2/TPC_Logging_Server.h
@@ -0,0 +1,87 @@
+/*
+** $Id$
+**
+** This is the Thread-per-connection logging server example from Chapter 7.
+**
+** Copyright 2002 Addison Wesley. All Rights Reserved.
+*/
+
+#ifndef _TPC_LOGGING_SERVER_H
+#define _TPC_LOGGING_SERVER_H
+
+#include "ace/Acceptor.h"
+#include "ace/INET_Addr.h"
+#include "ace/Reactor.h"
+#include "ace/Svc_Handler.h"
+#include "ace/FILE_IO.h"
+#include "Logging_Handler.h"
+
+#include "ace/SOCK_Acceptor.h"
+#include <openssl/ssl.h>
+
+class TPC_Logging_Handler
+ : public ACE_Svc_Handler<ACE_SOCK_STREAM, ACE_NULL_SYNCH> {
+protected:
+ ACE_FILE_IO log_file_; // File of log records.
+
+ // Connection to peer service handler.
+ Logging_Handler logging_handler_;
+
+public:
+ TPC_Logging_Handler () : logging_handler_ (log_file_) {}
+
+ virtual int open (void *);
+
+ virtual int svc (void) {
+ for (;;)
+ switch (logging_handler_.log_record ()) {
+ case -1: return -1; // Error.
+ case 0: return 0; // Client closed connection.
+ default: continue; // Default case.
+ }
+ /* NOTREACHED */
+ return 0;
+ }
+};
+
+
+class TPC_Logging_Acceptor
+ : public ACE_Acceptor<TPC_Logging_Handler, ACE_SOCK_ACCEPTOR> {
+protected:
+ // The SSL ``context'' data structure.
+ SSL_CTX *ssl_ctx_;
+
+ // The SSL data structure corresponding to authenticated
+ // SSL connections.
+ SSL *ssl_;
+
+public:
+ typedef ACE_Acceptor<TPC_Logging_Handler, ACE_SOCK_ACCEPTOR>
+ PARENT;
+ typedef ACE_SOCK_Acceptor::PEER_ADDR PEER_ADDR;
+
+ // Constructor.
+ TPC_Logging_Acceptor (ACE_Reactor *r)
+ : PARENT (r), ssl_ctx_ (0), ssl_ (0) {}
+
+ // Destructor frees the SSL resources.
+ virtual ~TPC_Logging_Acceptor (void) {
+ SSL_free (this->ssl_);
+ SSL_CTX_free (this->ssl_ctx_);
+ }
+
+ // Initialize the acceptor instance.
+ virtual int open
+ (const ACE_SOCK_Acceptor::PEER_ADDR &local_addr,
+ ACE_Reactor *reactor = ACE_Reactor::instance (),
+ int flags = 0, int use_select = 1, int reuse_addr = 1);
+
+ virtual int handle_close
+ (ACE_HANDLE = ACE_INVALID_HANDLE,
+ ACE_Reactor_Mask = ACE_Event_Handler::ALL_EVENTS_MASK);
+
+ // Connection establishment and authentication hook method.
+ virtual int accept_svc_handler (TPC_Logging_Handler *sh);
+};
+
+#endif /* _TPC_LOGGING_SERVER_H */
diff --git a/ACE/examples/C++NPv2/TPLS_export.h b/ACE/examples/C++NPv2/TPLS_export.h
new file mode 100644
index 00000000000..71448e71a50
--- /dev/null
+++ b/ACE/examples/C++NPv2/TPLS_export.h
@@ -0,0 +1,38 @@
+
+// -*- C++ -*-
+// $Id$
+// Definition for Win32 Export directives.
+// This file is generated automatically by generate_export_file.pl TPLS
+// ------------------------------
+#ifndef TPLS_EXPORT_H
+#define TPLS_EXPORT_H
+
+#include "ace/config-all.h"
+
+#if defined (ACE_AS_STATIC_LIBS) && !defined (TPLS_HAS_DLL)
+# define TPLS_HAS_DLL 0
+#endif /* ACE_AS_STATIC_LIBS && ! TPLS_HAS_DLL */
+
+#if !defined (TPLS_HAS_DLL)
+# define TPLS_HAS_DLL 1
+#endif /* ! TPLS_HAS_DLL */
+
+#if defined (TPLS_HAS_DLL) && (TPLS_HAS_DLL == 1)
+# if defined (TPLS_BUILD_DLL)
+# define TPLS_Export ACE_Proper_Export_Flag
+# define TPLS_SINGLETON_DECLARATION(T) ACE_EXPORT_SINGLETON_DECLARATION (T)
+# define TPLS_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) ACE_EXPORT_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK)
+# else /* TPLS_BUILD_DLL */
+# define TPLS_Export ACE_Proper_Import_Flag
+# define TPLS_SINGLETON_DECLARATION(T) ACE_IMPORT_SINGLETON_DECLARATION (T)
+# define TPLS_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) ACE_IMPORT_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK)
+# endif /* TPLS_BUILD_DLL */
+#else /* TPLS_HAS_DLL == 1 */
+# define TPLS_Export
+# define TPLS_SINGLETON_DECLARATION(T)
+# define TPLS_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK)
+#endif /* TPLS_HAS_DLL == 1 */
+
+#endif /* TPLS_EXPORT_H */
+
+// End of auto generated file.
diff --git a/ACE/examples/C++NPv2/TP_Logging_Server.cpp b/ACE/examples/C++NPv2/TP_Logging_Server.cpp
new file mode 100644
index 00000000000..7342cf4c757
--- /dev/null
+++ b/ACE/examples/C++NPv2/TP_Logging_Server.cpp
@@ -0,0 +1,70 @@
+/*
+** $Id$
+**
+** Copyright 2002 Addison Wesley. All Rights Reserved.
+*/
+
+#include "ace/OS_Memory.h"
+#include "ace/Guard_T.h"
+#include "ace/Message_Block.h"
+#include "TP_Logging_Server.h"
+
+int TP_Logging_Handler::handle_input (ACE_HANDLE) {
+ ACE_Message_Block *mblk = 0;
+ if (logging_handler_.recv_log_record (mblk) != -1) {
+ ACE_Message_Block *log_blk = 0;
+ ACE_NEW_RETURN
+ (log_blk, ACE_Message_Block
+ (reinterpret_cast<char *> (this)), -1);
+ log_blk->cont (mblk);
+ ACE_GUARD_RETURN (ACE_SYNCH_MUTEX, guard, lock_, -1);
+ if (TP_LOGGING_TASK::instance ()->put (log_blk) == -1)
+ { log_blk->release (); return -1; }
+ ++queued_count_;
+ return 0;
+ } else return -1;
+}
+
+
+int
+TP_Logging_Handler::handle_close (ACE_HANDLE handle,
+ ACE_Reactor_Mask) {
+ int close_now = 0;
+ if (handle != ACE_INVALID_HANDLE) {
+ ACE_GUARD_RETURN (ACE_SYNCH_MUTEX, guard, lock_, -1);
+ if (queued_count_ == 0)
+ close_now = 1;
+ else
+ deferred_close_ = 1;
+ } else {
+ ACE_GUARD_RETURN (ACE_SYNCH_MUTEX, guard, lock_, -1);
+ queued_count_--;
+ if (queued_count_ == 0) close_now = deferred_close_;
+ }
+
+ if (close_now)
+ return Logging_Event_Handler::handle_close ();
+ return 0;
+}
+
+
+int TP_Logging_Task::svc () {
+ for (ACE_Message_Block *log_blk; getq (log_blk) != -1; ) {
+ TP_Logging_Handler *tp_handler = reinterpret_cast<TP_Logging_Handler *> (log_blk->rd_ptr ());
+ Logging_Handler logging_handler (tp_handler->log_file ());
+ logging_handler.write_log_record (log_blk->cont ());
+
+ log_blk->release ();
+ tp_handler->handle_close (ACE_INVALID_HANDLE, 0);
+ }
+ return 0;
+}
+
+ACE_FACTORY_DEFINE (TPLS, TP_Logging_Server)
+
+#if defined (ACE_HAS_EXPLICIT_STATIC_TEMPLATE_MEMBER_INSTANTIATION)
+template ACE_Singleton<TP_Logging_Task, ACE_Null_Mutex> *
+ ACE_Singleton<TP_Logging_Task, ACE_Null_Mutex>::singleton_;
+template ACE_Unmanaged_Singleton<TP_Logging_Task, ACE_Null_Mutex> *
+ ACE_Unmanaged_Singleton<TP_Logging_Task, ACE_Null_Mutex>::singleton_;
+#endif /* ACE_HAS_EXPLICIT_STATIC_TEMPLATE_MEMBER_INSTANTIATION */
diff --git a/ACE/examples/C++NPv2/TP_Logging_Server.h b/ACE/examples/C++NPv2/TP_Logging_Server.h
new file mode 100644
index 00000000000..9c4869cdcee
--- /dev/null
+++ b/ACE/examples/C++NPv2/TP_Logging_Server.h
@@ -0,0 +1,131 @@
+/*
+** $Id$
+**
+** Copyright 2002 Addison Wesley. All Rights Reserved.
+*/
+
+#ifndef _TP_LOGGING_SERVER_H
+#define _TP_LOGGING_SERVER_H
+
+#include "ace/Auto_Ptr.h"
+#include "ace/Singleton.h"
+#include "ace/Synch.h"
+#include "ace/Task.h"
+#include "Logging_Acceptor.h"
+#include "Logging_Event_Handler.h"
+#include "Reactor_Logging_Server_T.h"
+#include "TPLS_export.h"
+
+class TP_Logging_Task : public ACE_Task<ACE_SYNCH> {
+ // Instantiated with an MT synchronization trait.
+public:
+ enum { MAX_THREADS = 4 };
+
+ virtual int open (void * = 0)
+ { return activate (THR_NEW_LWP, MAX_THREADS); }
+
+ virtual int put (ACE_Message_Block *mblk,
+ ACE_Time_Value *timeout = 0)
+ { return putq (mblk, timeout); }
+
+ virtual int svc (void);
+};
+
+typedef ACE_Unmanaged_Singleton<TP_Logging_Task, ACE_Null_Mutex>
+ TP_LOGGING_TASK;
+
+/*******************************************************/
+
+class TP_Logging_Acceptor;
+
+class TP_Logging_Handler : public Logging_Event_Handler {
+ friend class TP_Logging_Acceptor;
+protected:
+ virtual ~TP_Logging_Handler () {} // No-op destructor.
+
+ // Number of pointers to this class instance that currently
+ // reside in the <TP_LOGGING_TASK> singleton's message queue.
+ int queued_count_;
+
+ // Indicates whether <Logging_Event_Handler::handle_close()>
+ // must be called to cleanup and delete this object.
+ int deferred_close_;
+
+ // Serialize access to <queued_count_> and <deferred_close_>.
+ ACE_SYNCH_MUTEX lock_;
+
+public:
+ TP_Logging_Handler (ACE_Reactor *reactor)
+ : Logging_Event_Handler (reactor),
+ queued_count_ (0),
+ deferred_close_ (0) {}
+
+ // Called when input events occur, e.g., connection or data.
+ virtual int handle_input (ACE_HANDLE);
+
+ // Called when this object is destroyed, e.g., when it's
+ // removed from a reactor.
+ virtual int handle_close (ACE_HANDLE, ACE_Reactor_Mask);
+};
+
+/*******************************************************/
+
+class TP_Logging_Acceptor : public Logging_Acceptor {
+public:
+ TP_Logging_Acceptor (ACE_Reactor *r = ACE_Reactor::instance ())
+ : Logging_Acceptor (r) {}
+
+ virtual int handle_input (ACE_HANDLE) {
+ TP_Logging_Handler *peer_handler = 0;
+ ACE_NEW_RETURN (peer_handler,
+ TP_Logging_Handler (reactor ()), -1);
+ if (acceptor_.accept (peer_handler->peer ()) == -1) {
+ delete peer_handler;
+ return -1;
+ } else if (peer_handler->open () == -1)
+ peer_handler->handle_close (ACE_INVALID_HANDLE, 0);
+ return 0;
+ }
+};
+
+/*******************************************************/
+
+class TP_Logging_Server : public ACE_Service_Object {
+protected:
+ // Contains the reactor, acceptor, and handlers.
+ typedef Reactor_Logging_Server<TP_Logging_Acceptor>
+ LOGGING_DISPATCHER;
+ LOGGING_DISPATCHER *logging_dispatcher_;
+
+public:
+ TP_Logging_Server (): logging_dispatcher_ (0) {}
+
+ virtual int init (int argc, ACE_TCHAR *argv[]) {
+ int i;
+ char **array = 0;
+ ACE_NEW_RETURN (array, char*[argc], -1);
+ ACE_Auto_Array_Ptr<char *> char_argv (array);
+
+ for (i = 0; i < argc; ++i)
+ char_argv[i] = ACE::strnew (ACE_TEXT_ALWAYS_CHAR (argv[i]));
+ ACE_NEW_NORETURN
+ (logging_dispatcher_,
+ TP_Logging_Server::LOGGING_DISPATCHER
+ (i, char_argv.get (), ACE_Reactor::instance ()));
+ for (i = 0; i < argc; ++i) ACE::strdelete (char_argv[i]);
+ if (logging_dispatcher_ == 0) return -1;
+ else return TP_LOGGING_TASK::instance ()->open ();
+ }
+
+ virtual int fini () {
+ TP_LOGGING_TASK::instance ()->flush ();
+ TP_LOGGING_TASK::instance ()->wait ();
+ TP_LOGGING_TASK::close ();
+ delete logging_dispatcher_;
+ return 0;
+ }
+};
+
+ACE_FACTORY_DECLARE (TPLS, TP_Logging_Handler)
+
+#endif /* _TP_LOGGING_SERVER_H */
diff --git a/ACE/examples/C++NPv2/TP_Reactor_Logging_Server.cpp b/ACE/examples/C++NPv2/TP_Reactor_Logging_Server.cpp
new file mode 100644
index 00000000000..0d3216fe4e5
--- /dev/null
+++ b/ACE/examples/C++NPv2/TP_Reactor_Logging_Server.cpp
@@ -0,0 +1,117 @@
+/*
+** $Id$
+**
+** Copyright 2002 Addison Wesley. All Rights Reserved.
+*/
+
+// FUZZ: disable check_for_streams_include
+#include "ace/streams.h"
+
+#include "ace/Auto_Ptr.h"
+#include "ace/Reactor.h"
+#include "ace/TP_Reactor.h"
+#include "ace/Thread_Manager.h"
+
+#if defined (ACE_WIN32) && (!defined (ACE_HAS_STANDARD_CPP_LIBRARY) || \
+ (ACE_HAS_STANDARD_CPP_LIBRARY == 0) || \
+ defined (ACE_USES_OLD_IOSTREAMS))
+# include <stdio.h>
+#else
+# include <string>
+#endif
+
+#include "Reactor_Logging_Server_T.h"
+#include "Logging_Acceptor_Ex.h"
+
+typedef Reactor_Logging_Server<Logging_Acceptor_Ex>
+ Server_Logging_Daemon;
+
+
+class Quit_Handler : public ACE_Event_Handler {
+ friend class ace_dewarn_gplusplus;
+public:
+ Quit_Handler (ACE_Reactor *r) : ACE_Event_Handler (r) {}
+
+ virtual int handle_exception (ACE_HANDLE) {
+ reactor ()->end_reactor_event_loop ();
+ return -1; // Trigger call to handle_close() method.
+ }
+
+ virtual int handle_close (ACE_HANDLE, ACE_Reactor_Mask)
+ { delete this; return 0; }
+
+private:
+
+ // Private destructor ensures dynamic allocation.
+ virtual ~Quit_Handler () {}
+};
+
+
+static ACE_THR_FUNC_RETURN event_loop (void *arg) {
+ ACE_Reactor *reactor = static_cast<ACE_Reactor *> (arg);
+
+ reactor->owner (ACE_OS::thr_self ());
+ reactor->run_reactor_event_loop ();
+ return 0;
+}
+
+
+static ACE_THR_FUNC_RETURN controller (void *arg) {
+ ACE_Reactor *reactor = static_cast<ACE_Reactor *> (arg);
+
+ Quit_Handler *quit_handler = 0;
+ ACE_NEW_RETURN (quit_handler, Quit_Handler (reactor), 0);
+
+#if defined (ACE_WIN32) && (!defined (ACE_HAS_STANDARD_CPP_LIBRARY) || \
+ (ACE_HAS_STANDARD_CPP_LIBRARY == 0) || \
+ defined (ACE_USES_OLD_IOSTREAMS))
+ for (;;) {
+ char user_input[80];
+ fgets (user_input, sizeof (user_input), stdin);
+ if (ACE_OS::strcmp (user_input, "quit") == 0) {
+ reactor->notify (quit_handler);
+ break;
+ }
+ }
+#else
+ for (;;) {
+#if defined (ACE_USES_STD_NAMESPACE_FOR_STDCPP_LIB) && (ACE_USES_STD_NAMESPACE_FOR_STDCPP_LIB == 0)
+ string user_input;
+ getline (cin, user_input, '\n');
+#else
+ std::string user_input;
+ std::getline (cin, user_input, '\n');
+#endif
+ if (user_input == "quit") {
+ reactor->notify (quit_handler);
+ break;
+ }
+ }
+#endif
+
+ return 0;
+}
+
+
+int main (int argc, char *argv[])
+{
+ const size_t N_THREADS = 4;
+ ACE_TP_Reactor tp_reactor;
+ ACE_Reactor reactor (&tp_reactor);
+ auto_ptr<ACE_Reactor> delete_instance
+ (ACE_Reactor::instance (&reactor));
+
+ Server_Logging_Daemon *server;
+ // Ignore argv[0]...
+ --argc; ++argv;
+ ACE_NEW_RETURN (server,
+ Server_Logging_Daemon (argc, argv,
+ ACE_Reactor::instance ()),
+ 1);
+ ACE_Thread_Manager::instance ()->spawn_n
+ (N_THREADS, event_loop, ACE_Reactor::instance ());
+ ACE_Thread_Manager::instance ()->spawn
+ (controller, ACE_Reactor::instance ());
+ return ACE_Thread_Manager::instance ()->wait ();
+}
+
diff --git a/ACE/examples/C++NPv2/WFMO_Reactor_Logging_Server.cpp b/ACE/examples/C++NPv2/WFMO_Reactor_Logging_Server.cpp
new file mode 100644
index 00000000000..2174cd20412
--- /dev/null
+++ b/ACE/examples/C++NPv2/WFMO_Reactor_Logging_Server.cpp
@@ -0,0 +1,145 @@
+/*
+** $Id$
+**
+** Copyright 2002 Addison Wesley. All Rights Reserved.
+*/
+
+#include "ace/config-all.h"
+
+#if defined (ACE_WIN32)
+
+#include "ace/Reactor.h"
+#include "ace/WFMO_Reactor.h"
+#include "ace/Thread_Manager.h"
+#include "ace/OS_NS_string.h"
+
+#include "Reactor_Logging_Server_T.h"
+#include "Logging_Acceptor_Ex.h"
+#include "Logging_Event_Handler_Ex.h"
+
+class Quit_Handler : public ACE_Event_Handler {
+private:
+ ACE_Manual_Event quit_seen_;
+
+public:
+ Quit_Handler (ACE_Reactor *r) : ACE_Event_Handler (r) {
+ SetConsoleMode (ACE_STDIN, ENABLE_LINE_INPUT
+ | ENABLE_ECHO_INPUT
+ | ENABLE_PROCESSED_INPUT);
+ if (reactor ()->register_handler
+ (this, quit_seen_.handle ()) == -1
+ || ACE_Event_Handler::register_stdin_handler
+ (this, r, ACE_Thread_Manager::instance ()) == -1)
+ r->end_reactor_event_loop ();
+ }
+
+ ~Quit_Handler () {
+ ACE_Event_Handler::remove_stdin_handler
+ (reactor (), ACE_Thread_Manager::instance ());
+ reactor ()->remove_handler (quit_seen_.handle (),
+ ACE_Event_Handler::DONT_CALL);
+ }
+
+ virtual int handle_input (ACE_HANDLE h) {
+ CHAR user_input[BUFSIZ];
+ DWORD count;
+ if (!ReadFile (h, user_input, BUFSIZ, &count, 0))
+ return -1;
+
+ user_input[count] = '\0';
+ if (ACE_OS::strncmp (user_input, "quit", 4) == 0)
+ return -1;
+ return 0;
+ }
+
+ virtual int handle_close (ACE_HANDLE, ACE_Reactor_Mask) {
+ quit_seen_.signal ();
+ return 0;
+ }
+
+ virtual int handle_signal (int, siginfo_t *, ucontext_t *) {
+ reactor ()->end_reactor_event_loop ();
+ return 0;
+ }
+};
+
+
+class Logging_Event_Handler_WFMO : public Logging_Event_Handler_Ex
+{
+public:
+ Logging_Event_Handler_WFMO (ACE_Reactor *r)
+ : Logging_Event_Handler_Ex (r) {}
+
+protected:
+ int handle_input (ACE_HANDLE) {
+ ACE_GUARD_RETURN (ACE_SYNCH_MUTEX, monitor, lock_, -1);
+ return logging_handler_.log_record ();
+ }
+
+ ACE_Thread_Mutex lock_; // Serialize threads in thread pool.
+};
+
+
+class Logging_Acceptor_WFMO : public Logging_Acceptor_Ex
+{
+public:
+ // Simple constructor to pass ACE_Reactor to base class.
+ Logging_Acceptor_WFMO (ACE_Reactor *r = ACE_Reactor::instance ())
+ : Logging_Acceptor_Ex (r) {};
+
+protected:
+ virtual int handle_input (ACE_HANDLE) {
+ Logging_Event_Handler_WFMO *peer_handler = 0;
+ ACE_NEW_RETURN (peer_handler,
+ Logging_Event_Handler_WFMO (reactor ()),
+ -1);
+
+ if (acceptor_.accept (peer_handler->peer ()) == -1) {
+ delete peer_handler;
+ return -1;
+ } else if (peer_handler->open () == -1) {
+ peer_handler->handle_close ();
+ return -1;
+ }
+ return 0;
+ }
+};
+
+
+static ACE_THR_FUNC_RETURN event_loop (void *arg) {
+ ACE_Reactor *reactor = static_cast<ACE_Reactor *> (arg);
+
+ reactor->owner (ACE_OS::thr_self ());
+ reactor->run_reactor_event_loop ();
+ return 0;
+}
+
+
+typedef Reactor_Logging_Server<Logging_Acceptor_WFMO>
+ Server_Logging_Daemon;
+
+
+int main (int argc, char *argv[])
+{
+ const size_t N_THREADS = 4;
+ ACE_WFMO_Reactor wfmo_reactor;
+ ACE_Reactor reactor (&wfmo_reactor);
+
+ Server_Logging_Daemon *server;
+ // Ignore argv[0]...
+ --argc; ++argv;
+ ACE_NEW_RETURN (server,
+ Server_Logging_Daemon (argc, argv, &reactor),
+ 1);
+ Quit_Handler quit_handler (&reactor);
+ ACE_Thread_Manager::instance ()->spawn_n
+ (N_THREADS, event_loop, &reactor);
+ return ACE_Thread_Manager::instance ()->wait ();
+}
+
+#else /* !ACE_WIN32 */
+int main (int, char *[])
+{
+ return 0;
+}
+#endif /* ACE_WIN32 */
diff --git a/ACE/examples/C++NPv2/display_logfile.cpp b/ACE/examples/C++NPv2/display_logfile.cpp
new file mode 100644
index 00000000000..19f251e9463
--- /dev/null
+++ b/ACE/examples/C++NPv2/display_logfile.cpp
@@ -0,0 +1,361 @@
+/*
+** $Id$
+**
+** Copyright 2002 Addison Wesley. All Rights Reserved.
+*/
+
+#include "ace/ACE.h"
+#include "ace/CDR_Stream.h"
+#include "ace/FILE_Addr.h"
+#include "ace/FILE_Connector.h"
+#include "ace/FILE_IO.h"
+#include "ace/Message_Block.h"
+#include "ace/Module.h"
+#include "ace/SString.h"
+#include "ace/Stream.h"
+#include "ace/Task.h"
+#include "ace/Thread_Manager.h"
+#include "ace/Lock_Adapter_T.h"
+#include "ace/OS_NS_string.h"
+#include "ace/OS_NS_time.h"
+
+template <class TASK>
+class Logrec_Module : public ACE_Module<ACE_SYNCH>
+{
+public:
+ Logrec_Module (const ACE_TCHAR *name)
+ {
+ this->open (name,
+ &task_, // Initialize writer-side task.
+ 0, // Ignore reader-side task.
+ 0,
+ ACE_Module<ACE_SYNCH>::M_DELETE_READER);
+ }
+private:
+ TASK task_;
+};
+#define LOGREC_MODULE(NAME) \
+ typedef Logrec_Module<NAME> NAME##_Module
+
+class Logrec_Reader : public ACE_Task<ACE_SYNCH>
+{
+private:
+ ACE_TString filename_; // Name of logfile.
+ ACE_FILE_IO logfile_; // File containing log records.
+
+public:
+ enum {MB_CLIENT = ACE_Message_Block::MB_USER,
+ MB_TYPE, MB_PID, MB_TIME, MB_TEXT};
+
+ Logrec_Reader (const ACE_TString &file): filename_ (file) {}
+
+ virtual int open (void *) {
+ ACE_FILE_Addr name (filename_.c_str ());
+ ACE_FILE_Connector connector;
+ if (connector.connect (logfile_, name) == -1)
+ return -1;
+ return activate ();
+ }
+
+ virtual int svc () {
+ const size_t FileReadSize = 8 * 1024;
+ ACE_Message_Block mblk (FileReadSize);
+
+ for (;; mblk.crunch ()) {
+ // Read as much as will fit in the message block.
+ ssize_t bytes_read = logfile_.recv (mblk.wr_ptr (),
+ mblk.space ());
+ if (bytes_read <= 0)
+ break;
+ mblk.wr_ptr (static_cast<size_t> (bytes_read));
+
+ // We have a bunch of data from the log file. The data is
+ // arranged like so:
+ // hostname\0
+ // CDR-encoded log record
+ // So, first we scan for the end of the host name, then
+ // initialize another ACE_Message_Block aligned for CDR
+ // demarshaling and copy the remainder of the block into it. We
+ // can't use duplicate() because we need to be sure the data
+ // pointer is aligned properly for CDR demarshaling. If at any
+ // point, there's not enough data left in the message block to
+ // extract what's needed, crunch the block to move all remaining
+ // data to the beginning and read more from the file.
+ for (;;) {
+ size_t name_len = ACE_OS::strnlen
+ (mblk.rd_ptr (), mblk.length ());
+ if (name_len == mblk.length ()) break;
+
+ char *name_p = mblk.rd_ptr ();
+ ACE_Message_Block *rec, *head, *temp;
+ ACE_NEW_RETURN
+ (head, ACE_Message_Block (name_len, MB_CLIENT), 0);
+ head->copy (name_p, name_len);
+ mblk.rd_ptr (name_len + 1); // Skip nul also
+
+ size_t need = mblk.length () + ACE_CDR::MAX_ALIGNMENT;
+ ACE_NEW_RETURN (rec, ACE_Message_Block (need), 0);
+ ACE_CDR::mb_align (rec);
+ rec->copy (mblk.rd_ptr (), mblk.length ());
+
+ // Now rec contains the remaining data we've read so far from
+ // the file. Create an ACE_InputCDR to start demarshaling the
+ // log record, header first to find the length, then the data.
+ // Since the ACE_InputCDR constructor increases the reference count
+ // on rec, we release it upon return to prevent leaks.
+ // The cdr 'read' methods return 0 on failure, 1 on success.
+ ACE_InputCDR cdr (rec); rec->release ();
+ ACE_CDR::Boolean byte_order;
+ if (!cdr.read_boolean (byte_order)) {
+ head->release (); rec->release (); break;
+ }
+ cdr.reset_byte_order (byte_order);
+
+ // Now read the length of the record. From there, we'll know
+ // if rec contains the complete record or not.
+ ACE_CDR::ULong length;
+ if (!cdr.read_ulong (length)) {
+ head->release (); mblk.rd_ptr (name_p); break;
+ }
+ if (length > cdr.length ()) {
+ head->release (); mblk.rd_ptr (name_p); break;
+ }
+
+ // The complete record is in rec... grab all the fields into
+ // separate, chained message blocks.
+ ACE_NEW_RETURN (temp,
+ ACE_Message_Block (length, MB_TEXT),
+ 0);
+ ACE_NEW_RETURN
+ (temp,
+ ACE_Message_Block (2 * sizeof (ACE_CDR::Long),
+ MB_TIME, temp),
+ 0);
+ ACE_NEW_RETURN
+ (temp,
+ ACE_Message_Block (sizeof (ACE_CDR::Long),
+ MB_PID, temp),
+ 0);
+ ACE_NEW_RETURN
+ (temp,
+ ACE_Message_Block (sizeof (ACE_CDR::Long),
+ MB_TYPE, temp),
+ 0);
+ head->cont (temp);
+
+ // Extract the type
+ ACE_CDR::Long *lp;
+ lp = reinterpret_cast<ACE_CDR::Long*> (temp->wr_ptr ());
+ cdr >> *lp;
+ temp->wr_ptr (sizeof (ACE_CDR::Long));
+ temp = temp->cont ();
+
+ // Extract the pid
+ lp = reinterpret_cast<ACE_CDR::Long*> (temp->wr_ptr ());
+ cdr >> *lp;
+ temp->wr_ptr (sizeof (ACE_CDR::Long));
+ temp = temp->cont ();
+
+ // Extract the timestamp (2 Longs)
+ lp = reinterpret_cast<ACE_CDR::Long*> (temp->wr_ptr ());
+ cdr >> *lp; ++lp; cdr >> *lp;
+ temp->wr_ptr (2 * sizeof (ACE_CDR::Long));
+ temp = temp->cont ();
+
+ // Demarshal the length of the message text, then demarshal
+ // the text into the block.
+ ACE_CDR::ULong text_len;
+ cdr >> text_len;
+ cdr.read_char_array (temp->wr_ptr (), text_len);
+ temp->wr_ptr (text_len);
+
+ // Forward the whole lot to the next module.
+ if (put_next (head) == -1) break;
+
+ // Move the file-content block's read pointer up past whatever
+ // was just processed. Although the mblk's rd_ptr has not been
+ // moved, cdr's has. Therefore, use its length() to determine
+ // how much is left.
+ mblk.rd_ptr (mblk.length () - cdr.length ());
+ }
+ }
+
+ // Now that the file is done, send a block down the stream to tell
+ // the other modules to stop.
+ ACE_Message_Block *stop;
+ ACE_NEW_RETURN
+ (stop, ACE_Message_Block (0, ACE_Message_Block::MB_STOP),
+ 0);
+ put_next (stop);
+ return 0;
+ }
+};
+
+class Logrec_Reader_Module : public ACE_Module<ACE_SYNCH>
+{
+public:
+ Logrec_Reader_Module (const ACE_TString &filename)
+ : task_ (filename)
+ {
+ this->open (ACE_TEXT ("Logrec Reader"),
+ &task_, // Initialize writer-side.
+ 0, // Ignore reader-side.
+ 0,
+ ACE_Module<ACE_SYNCH>::M_DELETE_READER);
+ }
+private:
+ Logrec_Reader task_;
+};
+
+class Logrec_Writer : public ACE_Task<ACE_SYNCH>
+{
+public:
+ // Initialization hook method.
+ virtual int open (void *) { return activate (); }
+
+ virtual int put (ACE_Message_Block *mblk, ACE_Time_Value *to)
+ { return putq (mblk, to); }
+
+ virtual int svc () {
+ int stop = 0;
+ for (ACE_Message_Block *mb; !stop && getq (mb) != -1; ) {
+ if (mb->msg_type () == ACE_Message_Block::MB_STOP)
+ stop = 1;
+ else
+ ACE::write_n (ACE_STDOUT, mb);
+ put_next (mb);
+ }
+ return 0;
+ }
+};
+
+LOGREC_MODULE (Logrec_Writer);
+
+class Logrec_Formatter : public ACE_Task<ACE_SYNCH>
+{
+public:
+ typedef void (*FORMATTER[5])(ACE_Message_Block *);
+private:
+ static FORMATTER format_; // Array of format static methods.
+
+public:
+ virtual int put (ACE_Message_Block *mblk, ACE_Time_Value *) {
+ if (mblk->msg_type () == Logrec_Reader::MB_CLIENT)
+ for (ACE_Message_Block *temp = mblk;
+ temp != 0;
+ temp = temp->cont ()) {
+ int mb_type =
+ temp->msg_type () - ACE_Message_Block::MB_USER;
+ (*format_[mb_type])(temp);
+ }
+ return put_next (mblk);
+ }
+
+ static void format_client (ACE_Message_Block *) {
+ return;
+ }
+
+ static void format_type (ACE_Message_Block *mblk) {
+ ACE_CDR::Long type = * (ACE_CDR::Long *)mblk->rd_ptr ();
+ mblk->size (11); // Max size in ASCII of 32-bit word.
+ mblk->reset ();
+ mblk->wr_ptr ((size_t) sprintf (mblk->wr_ptr (), "%d", type));
+ }
+
+ static void format_pid (ACE_Message_Block *mblk) {
+ ACE_CDR::Long pid = * (ACE_CDR::Long *)mblk->rd_ptr ();
+ mblk->size (11); // Max size in ASCII of 32-bit word.
+ mblk->reset ();
+ mblk->wr_ptr ((size_t) sprintf (mblk->wr_ptr (), "%d", pid));
+ }
+
+ static void format_time (ACE_Message_Block *mblk) {
+ ACE_CDR::Long secs = * (ACE_CDR::Long *)mblk->rd_ptr ();
+ mblk->rd_ptr (sizeof (ACE_CDR::Long));
+ ACE_CDR::Long usecs = * (ACE_CDR::Long *)mblk->rd_ptr ();
+ ACE_TCHAR timestamp_t[26];
+ char timestamp[26]; // Max size of ctime_r() string.
+ time_t time_secs (secs);
+ ACE_OS::ctime_r (&time_secs, timestamp_t, sizeof timestamp_t);
+ ACE_OS::strcpy (timestamp, ACE_TEXT_ALWAYS_CHAR (timestamp_t));
+ mblk->size (26); // Max size of ctime_r() string.
+ mblk->reset ();
+ timestamp[19] = '\0'; // NUL-terminate after the time.
+ timestamp[24] = '\0'; // NUL-terminate after the date.
+ size_t fmt_len (sprintf (mblk->wr_ptr (),
+ "%s.%03d %s",
+ timestamp + 4,
+ usecs / 1000,
+ timestamp + 20));
+ mblk->wr_ptr (fmt_len);
+ }
+
+ static void format_data (ACE_Message_Block *) {
+ return;
+ }
+};
+
+Logrec_Formatter::FORMATTER Logrec_Formatter::format_ = {
+ format_client, format_type, format_pid, format_time, format_data
+};
+
+LOGREC_MODULE (Logrec_Formatter);
+
+class Logrec_Separator : public ACE_Task<ACE_SYNCH>
+{
+private:
+ ACE_Lock_Adapter<ACE_SYNCH_MUTEX> lock_strategy_;
+
+public:
+ virtual int put (ACE_Message_Block *mblk,
+ ACE_Time_Value *) {
+ if (mblk->msg_type () != ACE_Message_Block::MB_STOP) {
+ ACE_Message_Block *separator;
+ ACE_NEW_RETURN
+ (separator,
+ ACE_Message_Block (ACE_OS::strlen ("|") + 1,
+ ACE_Message_Block::MB_DATA,
+ 0, 0, 0, &lock_strategy_),
+ -1);
+ separator->copy ("|");
+
+ ACE_Message_Block *dup = 0;
+ for (ACE_Message_Block *temp = mblk; temp != 0; ) {
+ dup = separator->duplicate ();
+ dup->cont (temp->cont ());
+ temp->cont (dup);
+ temp = dup->cont ();
+ }
+ ACE_Message_Block *nl;
+ ACE_NEW_RETURN (nl, ACE_Message_Block (2), 0);
+ nl->copy ("\n");
+ dup->cont (nl);
+ separator->release ();
+ }
+ return put_next (mblk);
+ }
+};
+
+LOGREC_MODULE (Logrec_Separator);
+
+int ACE_TMAIN (int argc, ACE_TCHAR *argv[])
+{
+ if (argc != 2)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "usage: %s logfile\n", argv[0]),
+ 1);
+ ACE_TString logfile (argv[1]);
+ ACE_Stream<ACE_SYNCH> stream;
+
+ if (stream.push
+ (new Logrec_Writer_Module (ACE_TEXT ("Writer"))) != -1
+ && stream.push
+ (new Logrec_Separator_Module (ACE_TEXT ("Separator"))) != -1
+ && stream.push
+ (new Logrec_Formatter_Module (ACE_TEXT ("Formatter"))) != -1
+ && stream.push
+ (new Logrec_Reader_Module (logfile)) != -1)
+ return ACE_Thread_Manager::instance ()->wait () == 0 ? 0 : 1;
+ return 1;
+}
+
diff --git a/ACE/examples/C++NPv2/svc.conf b/ACE/examples/C++NPv2/svc.conf
new file mode 100644
index 00000000000..e97f3748cf6
--- /dev/null
+++ b/ACE/examples/C++NPv2/svc.conf
@@ -0,0 +1,8 @@
+static Service_Reporter "-p $SERVICE_REPORTER_PORT"
+
+dynamic AIO_Client_Logging_Daemon Service_Object *
+AIO_CLD:_make_AIO_Client_Logging_Daemon()
+ "-p 7777"
+
+dynamic Server_Logging_Daemon Service_Object *
+TPCLS:_make_TPC_Logging_Server()
diff --git a/ACE/examples/ConfigViewer/ConfigTreeCtrl.cpp b/ACE/examples/ConfigViewer/ConfigTreeCtrl.cpp
new file mode 100644
index 00000000000..7700272b9ba
--- /dev/null
+++ b/ACE/examples/ConfigViewer/ConfigTreeCtrl.cpp
@@ -0,0 +1,229 @@
+// $Id$
+#include "stdafx.h"
+#include "ConfigTreeCtrl.h"
+#include "MainFrame.h"
+#include "ValueDlg.h"
+#include "ValueListCtrl.h"
+
+enum {CFGNEWKEY=100, CFGNEWSTRING, CFGNEWUINT, CFGNEWBINARY, CFGNEWSUBMENU, CFGFIND, CFGDELETE, CFGRENAME, CFGCOPYKEYNAME};
+
+
+BEGIN_EVENT_TABLE(ConfigTreeCtrl, wxTreeCtrl)
+ EVT_RIGHT_DOWN(ConfigTreeCtrl::OnRightDown)
+ EVT_RIGHT_UP(ConfigTreeCtrl::OnRightUp)
+ EVT_MENU(CFGNEWKEY, ConfigTreeCtrl::OnNewKey)
+ EVT_MENU(CFGNEWSTRING, ConfigTreeCtrl::OnNewString)
+ EVT_MENU(CFGNEWUINT, ConfigTreeCtrl::OnNewUINT)
+ EVT_MENU(CFGNEWBINARY, ConfigTreeCtrl::OnNewBinary)
+ EVT_MENU(CFGFIND, ConfigTreeCtrl::OnFind)
+ EVT_MENU(CFGDELETE, ConfigTreeCtrl::OnDelete)
+ EVT_TREE_SEL_CHANGED(FRAME_TREE, ConfigTreeCtrl::OnSelChanged)
+END_EVENT_TABLE()
+
+
+ConfigTreeCtrl::ConfigTreeCtrl(wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style, const wxValidator& validator, const wxString& name)
+: wxTreeCtrl(parent, id, pos, size, style, validator, name)
+{
+ // Load the tree
+ LoadTree();
+}
+
+ConfigTreeCtrl::~ConfigTreeCtrl()
+{
+}
+
+void ConfigTreeCtrl::LoadTree()
+{
+ m_pConfig = MainFrame::Instance()->GetpConfig();
+ const ACE_Configuration_Section_Key& Key = m_pConfig->root_section();
+ wxTreeItemId Root = AppendItem(GetRootItem(), "Root");
+ LoadSection(Root, Key);
+}
+
+void ConfigTreeCtrl::LoadSection(wxTreeItemId& ParentItem, const ACE_Configuration_Section_Key& Key)
+{
+ ACE_TString Name;
+ int Index = 0;
+ while(!m_pConfig->enumerate_sections(Key, Index, Name))
+ {
+ wxTreeItemId Item = AppendItem(ParentItem, Name.fast_rep());
+ ACE_Configuration_Section_Key Child;
+ m_pConfig->open_section(Key, Name.fast_rep(), 0, Child);
+ LoadSection( Item, Child);
+ ++Index;
+ }
+}
+
+void ConfigTreeCtrl::OnRightDown(wxMouseEvent& event)
+{
+ //EndEditLabel(TRUE);
+ int Flags = wxTREE_HITTEST_ONITEMLABEL | wxTREE_HITTEST_ONITEMICON;
+ long ItemID = HitTest(wxPoint(event.m_x, event.m_y), Flags);
+ SelectItem(ItemID);
+}
+
+void ConfigTreeCtrl::OnRightUp(wxMouseEvent& event)
+{
+ wxTreeItemId ItemID = GetSelection();
+
+ wxMenu* pMenu = new wxMenu;
+ wxMenu* pNewMenu = new wxMenu;
+ pNewMenu->Append(CFGNEWKEY, "Key");
+ pNewMenu->AppendSeparator();
+ pNewMenu->Append(CFGNEWSTRING, "String");
+ pNewMenu->Append(CFGNEWUINT, "Unsigned Int");
+ //pNewMenu->Append(CFGNEWBINARY, "Binary");
+ pMenu->Append(CFGNEWSUBMENU, "New", pNewMenu);
+ pMenu->Append(CFGFIND, "Find");
+ pMenu->AppendSeparator();
+ pMenu->Append(CFGDELETE, "Delete");
+ //pMenu->Append(CFGRENAME, "Rename"); // not supported
+ //pMenu->AppendSeparator();
+ //pMenu->Append(CFGCOPYKEYNAME, "Copy Key Name"); // not supported
+ PopupMenu(pMenu, event.m_x, event.m_y);
+ delete pMenu;
+}
+
+void ConfigTreeCtrl::ResolveKey(wxTreeItemId Item, ACE_Configuration_Section_Key& Key)
+{
+ wxTreeItemId OriginalItem = Item;
+ ACE_TString Path("");
+ ACE_TString Temp;
+ while(Item != GetRootItem())
+ {
+ wxString Text = GetItemText(Item);
+ Temp = Path;
+ Path = Text.c_str();
+ if(Temp.length())
+ {
+ Path += "\\";
+ Path += Temp;
+ }
+ Item = GetParent(Item);
+ }
+ if(Path.length())
+ {
+ m_pConfig->expand_path(m_pConfig->root_section(), Path, Key, 0);
+ }
+ else
+ {
+ Key = m_pConfig->root_section();
+ }
+}
+
+
+void ConfigTreeCtrl::OnNewKey(wxCommandEvent& event)
+{
+ wxTextEntryDialog Dlg(this, "Test", "Key Name");
+ if(Dlg.ShowModal() != wxID_OK)
+ {
+ return;
+ }
+
+ wxString Value = Dlg.GetValue();
+
+ // Get the key for this node
+ wxTreeItemId ItemID = GetSelection();
+ ACE_Configuration_Section_Key Key, NewKey;
+ ResolveKey(ItemID, Key);
+ m_pConfig->open_section(Key, Value, 1, NewKey);
+ wxTreeItemId NewItemID = AppendItem(ItemID, Value);
+ EnsureVisible(NewItemID);
+}
+
+void ConfigTreeCtrl::OnNewString(wxCommandEvent& event)
+{
+ ValueDlg Dlg(this, true);
+ if(Dlg.ShowModal() != wxID_OK)
+ {
+ return;
+ }
+
+ ACE_TString Value = Dlg.GetStringValue();
+ ACE_TString Name = Dlg.GetName();
+
+ // Get the key for this node
+ wxTreeItemId ItemID = GetSelection();
+ ACE_Configuration_Section_Key Key;
+ ResolveKey(ItemID, Key);
+ m_pConfig->set_string_value(Key, Name.fast_rep(), Value);
+ m_pListCtrl->DisplaySection(Key);
+}
+
+void ConfigTreeCtrl::OnNewUINT(wxCommandEvent& event)
+{
+ ValueDlg Dlg(this, false);
+ if(Dlg.ShowModal() != wxID_OK)
+ {
+ return;
+ }
+
+ u_int Value = Dlg.GetUINTValue();
+ ACE_TString Name = Dlg.GetName();
+
+ // Get the key for this node
+ wxTreeItemId ItemID = GetSelection();
+ ACE_Configuration_Section_Key Key;
+ ResolveKey(ItemID, Key);
+ m_pConfig->set_integer_value(Key, Name.fast_rep(), Value);
+ m_pListCtrl->DisplaySection(Key);
+}
+
+void ConfigTreeCtrl::OnNewBinary(wxCommandEvent& event)
+{
+ assert(0);
+ /*
+ ValueDlg Dlg(this, true);
+ if(Dlg.ShowModal() != wxID_OK)
+ {
+ return;
+ }
+
+ ACE_TString Value = Dlg.GetStringValue();
+ ACE_TString Name = Dlg.GetName();
+
+ // Get the key for this node
+ wxTreeItemId ItemID = GetSelection();
+ ACE_Configuration_Section_Key Key;
+ ResolveKey(ItemID, Key);
+ m_pConfig->set_string_value(Key, Name.fast_rep(), Value);
+ m_pListCtrl->DisplaySection(Key);
+ */
+}
+
+void ConfigTreeCtrl::OnSelChanged(wxTreeEvent& event)
+{
+ wxTreeItemId ItemID = GetSelection();
+ ACE_Configuration_Section_Key Key;
+ ResolveKey(ItemID, Key);
+ m_pListCtrl->DisplaySection(Key);
+}
+
+void ConfigTreeCtrl::OnFind(wxCommandEvent& event)
+{
+}
+
+void ConfigTreeCtrl::OnDelete(wxCommandEvent& event)
+{
+ wxTreeItemId ItemID = GetSelection();
+ wxTreeItemId Parent = GetParent(ItemID);
+ ACE_Configuration_Section_Key Key;
+ ResolveKey(Parent, Key);
+ wxMessageDialog Dlg(this, "Are you sure you want to delete this section?", "Confirm Section Delete", wxYES_NO | wxICON_EXCLAMATION );
+ if(Dlg.ShowModal() != wxID_YES)
+ {
+ return;
+ }
+ wxString Text = GetItemText(ItemID);
+ m_pConfig->remove_section(Key, Text, 1);
+ // Reload parent
+ Delete(ItemID);
+}
+
+void ConfigTreeCtrl::ChangeConfig(ACE_Configuration* pConfig)
+{
+ m_pConfig = pConfig;
+ DeleteAllItems();
+ LoadTree();
+}
+
diff --git a/ACE/examples/ConfigViewer/ConfigTreeCtrl.h b/ACE/examples/ConfigViewer/ConfigTreeCtrl.h
new file mode 100644
index 00000000000..e44eb837384
--- /dev/null
+++ b/ACE/examples/ConfigViewer/ConfigTreeCtrl.h
@@ -0,0 +1,52 @@
+/* -*- C++ -*- */
+// $Id$
+
+#ifndef _ConfigurationViewer_ConfigTreeCtrl_H
+#define _ConfigurationViewer_ConfigTreeCtrl_H
+
+class ValueListCtrl;
+
+class ConfigTreeCtrl : public wxTreeCtrl
+{
+public:
+ ///////////////////////////////////////////
+ // Initializers
+ ///////////////////////////////////////////
+ ConfigTreeCtrl(wxWindow* parent, wxWindowID id, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxTR_HAS_BUTTONS, const wxValidator& validator = wxDefaultValidator, const wxString& name = "listCtrl");
+ virtual ~ConfigTreeCtrl();
+
+ ///////////////////////////////////////////
+ // Methods
+ ///////////////////////////////////////////
+ void LoadTree();
+ void OnRightDown(wxMouseEvent& event);
+ void OnRightUp(wxMouseEvent& event);
+ void OnNewKey(wxCommandEvent& event);
+ void OnNewString(wxCommandEvent& event);
+ void OnNewUINT(wxCommandEvent& event);
+ void OnNewBinary(wxCommandEvent& event);
+ void OnFind(wxCommandEvent& event);
+ void OnDelete(wxCommandEvent& event);
+ void OnSelChanged(wxTreeEvent& event);
+ void ChangeConfig(ACE_Configuration* pConfig);
+ ///////////////////////////////////////////
+ // Attribute Accessors
+ ///////////////////////////////////////////
+ void SetpListCtrl(ValueListCtrl* pListCtrl) {m_pListCtrl = pListCtrl;};
+
+protected:
+ // Not Used
+ ConfigTreeCtrl(const ConfigTreeCtrl& RHS);
+ const ConfigTreeCtrl& operator=(const ConfigTreeCtrl& RHS);
+
+ void LoadSection(wxTreeItemId& ParentItem, const ACE_Configuration_Section_Key& Key);
+ void ResolveKey(wxTreeItemId Item, ACE_Configuration_Section_Key& Key);
+private:
+ DECLARE_EVENT_TABLE()
+
+ ACE_Configuration* m_pConfig;
+ ValueListCtrl* m_pListCtrl;
+};
+
+#endif
+
diff --git a/ACE/examples/ConfigViewer/ConfigViewer.mpc b/ACE/examples/ConfigViewer/ConfigViewer.mpc
new file mode 100644
index 00000000000..7927fb9b694
--- /dev/null
+++ b/ACE/examples/ConfigViewer/ConfigViewer.mpc
@@ -0,0 +1,7 @@
+// -*- MPC -*-
+// $Id$
+
+project : aceexe, wxwindows {
+ pch_header = stdafx.h
+ pch_source = stdafx.cpp
+} \ No newline at end of file
diff --git a/ACE/examples/ConfigViewer/ConfigurationViewer.cpp b/ACE/examples/ConfigViewer/ConfigurationViewer.cpp
new file mode 100644
index 00000000000..20d3dc02d2e
--- /dev/null
+++ b/ACE/examples/ConfigViewer/ConfigurationViewer.cpp
@@ -0,0 +1,45 @@
+// $Id$
+#ifdef __GNUG__
+ #pragma implementation "minimal.cpp"
+ #pragma interface "minimal.cpp"
+#endif
+
+#include "stdafx.h"
+#include "MainFrame.h"
+
+#ifdef __BORLANDC__
+ #pragma hdrstop
+#endif
+
+// the application icon
+#if defined(__WXGTK__) || defined(__WXMOTIF__)
+ #include "mondrian.xpm"
+#endif
+
+class ConfigurationViewerApp : public wxApp
+{
+public:
+ virtual bool OnInit();
+};
+
+IMPLEMENT_APP(ConfigurationViewerApp)
+
+bool ConfigurationViewerApp::OnInit()
+{
+ // Create the main application window
+ MainFrame *frame = new MainFrame("Configuration Viewer",
+ wxPoint(50, 50), wxSize(450, 340));
+
+ // Give it an icon
+#ifdef __WXMSW__
+ frame->SetIcon(wxIcon("mondrian"));
+#else
+ frame->SetIcon(wxIcon( mondrian_xpm ));
+#endif
+
+ frame->Show(TRUE);
+ SetTopWindow(frame);
+
+ return TRUE;
+}
+
diff --git a/ACE/examples/ConfigViewer/ConfigurationViewer.rc b/ACE/examples/ConfigViewer/ConfigurationViewer.rc
new file mode 100644
index 00000000000..f490ccefc2d
--- /dev/null
+++ b/ACE/examples/ConfigViewer/ConfigurationViewer.rc
@@ -0,0 +1,9 @@
+/* -*- C++ -*- */
+// $Id$
+
+#include "wx/msw/wx.rc"
+mondrian ICON "mondrian.ico"
+
+#define MINIMAL_QUIT 1
+#define MINIMAL_ABOUT 102
+
diff --git a/ACE/examples/ConfigViewer/MainFrame.cpp b/ACE/examples/ConfigViewer/MainFrame.cpp
new file mode 100644
index 00000000000..ace1c1c5e52
--- /dev/null
+++ b/ACE/examples/ConfigViewer/MainFrame.cpp
@@ -0,0 +1,199 @@
+// $Id$
+#include "stdafx.h"
+#include "MainFrame.h"
+#include "ConfigTreeCtrl.h"
+#include "ValueListCtrl.h"
+
+// Singleton
+MainFrame* MainFrame::m_pInstance = 0;
+
+// IDs for the controls and the menu commands
+
+BEGIN_EVENT_TABLE(MainFrame, wxFrame)
+ EVT_MENU(FILE_NEW_PERSISTENT_HEAP, MainFrame::OnFileNewPersistentHeap)
+ EVT_MENU(FILE_NEW_TRANSIENT_HEAP, MainFrame::OnFileNewTransientHeap)
+ EVT_MENU(FILE_OPEN_PERSISTENT_HEAP, MainFrame::OnFileOpenPersistentHeap)
+ EVT_MENU(FILE_OPEN_REGISTRY, MainFrame::OnFileOpenRegistry)
+ EVT_MENU(FILE_EXPORT, MainFrame::OnFileExport)
+ EVT_MENU(FILE_IMPORT, MainFrame::OnFileImport)
+ EVT_MENU(QUIT, MainFrame::OnQuit)
+ EVT_MENU(ABOUT, MainFrame::OnAbout)
+END_EVENT_TABLE()
+
+// frame constructor
+MainFrame::MainFrame(const wxString& title, const wxPoint& pos, const wxSize& size)
+: wxFrame((wxFrame *)NULL, -1, title, pos, size),
+ m_pConfig(0)
+{
+ m_pInstance = this;
+
+ // Create a persistent heap based configuration
+
+ ACE_Configuration_Heap* pHeapConfig = new ACE_Configuration_Heap;
+ pHeapConfig->open();
+ m_pConfig = pHeapConfig;
+
+ // set the frame icon
+ SetIcon(wxICON(mondrian));
+
+ // Create Splitter
+ m_pSplitter = new wxSplitterWindow(this, -1);
+ wxSize sz( m_pSplitter->GetSize() );
+ sz.SetWidth(sz.GetWidth() / 2);
+
+ // List Control
+ m_pListCtrl = new ValueListCtrl(m_pSplitter, -1, wxDefaultPosition, sz);
+
+ // Tree Control
+ m_pTreeCtrl = new ConfigTreeCtrl(m_pSplitter, FRAME_TREE, wxDefaultPosition, sz,
+ wxTR_EDIT_LABELS | wxTR_HAS_BUTTONS | wxTR_LINES_AT_ROOT);
+ m_pTreeCtrl->SetpListCtrl(m_pListCtrl);
+
+
+ // Setup splitter
+ m_pSplitter->SplitVertically(m_pTreeCtrl, m_pListCtrl);
+ m_pSplitter->SetMinimumPaneSize(100);
+ m_pSplitter->SetSashPosition(size.GetWidth() / 3);
+
+ // create a menu bar
+ wxMenu *menuFile = new wxMenu("", wxMENU_TEAROFF);
+ menuFile->Append(FILE_NEW_PERSISTENT_HEAP, "New Persistent Heap", "Create a new persistent heap");
+ menuFile->Append(FILE_NEW_TRANSIENT_HEAP, "New Transient Heap", "Create a new transient heap");
+ menuFile->Append(FILE_OPEN_PERSISTENT_HEAP, "Open Persistent Heap", "Open Persistent Heap");
+#if defined (ACE_WIN32)
+ menuFile->Append(FILE_OPEN_REGISTRY, "Open Win32 Registry", "Open Win32 Registry");
+#endif
+ menuFile->AppendSeparator();
+ menuFile->Append(FILE_IMPORT, "Import from INI file", "Import from INI file");
+ menuFile->Append(FILE_EXPORT, "Export to INI file", "Export to INI file");
+ menuFile->AppendSeparator();
+ menuFile->Append(ABOUT, "&About...\tCtrl-A", "Show about dialog");
+ menuFile->AppendSeparator();
+ menuFile->Append(QUIT, "E&xit\tAlt-X", "Quit this program");
+
+ // now append the freshly created menu to the menu bar...
+ wxMenuBar *menuBar = new wxMenuBar();
+ menuBar->Append(menuFile, "&File");
+
+ // ... and attach this menu bar to the frame
+ SetMenuBar(menuBar);
+
+#if wxUSE_STATUSBAR
+ CreateStatusBar(2);
+ SetStatusText("Ready");
+#endif // wxUSE_STATUSBAR
+}
+
+
+MainFrame::~MainFrame()
+{
+ delete m_pConfig;
+ m_pInstance = 0;
+}
+
+MainFrame* MainFrame::Instance()
+{
+ assert(m_pInstance);
+ return m_pInstance;
+}
+
+
+// event handlers
+
+void MainFrame::OnSize(wxSizeEvent& event)
+{
+ wxLayoutAlgorithm layout;
+ layout.LayoutFrame(this, m_pListCtrl);
+}
+
+
+void MainFrame::OnQuit(wxCommandEvent& WXUNUSED(event))
+{
+ // TRUE is to force the frame to close
+ Close(TRUE);
+}
+
+void MainFrame::OnAbout(wxCommandEvent& WXUNUSED(event))
+{
+ wxString msg;
+ msg.Printf( _T("Configuration Viewer v1.0\nWritten by Chris Hafey (chris@stentorsoft.com)\n"));
+ wxMessageBox(msg, "About", wxOK | wxICON_INFORMATION, this);
+}
+
+void MainFrame::OnFileNewPersistentHeap(wxCommandEvent& event)
+{
+ wxFileDialog Dlg(this, "Enter Filename:", "", "", "*.*", 0);
+ if(Dlg.ShowModal() != wxID_OK)
+ {
+ return;
+ }
+ delete m_pConfig;
+ ACE_Configuration_Heap* pHeapConfig = new ACE_Configuration_Heap;
+ pHeapConfig->open(Dlg.GetFilename());
+ SetNewConfig(pHeapConfig);
+}
+
+void MainFrame::OnFileNewTransientHeap(wxCommandEvent& event)
+{
+ delete m_pConfig;
+ ACE_Configuration_Heap* pHeapConfig = new ACE_Configuration_Heap;
+ pHeapConfig->open();
+ SetNewConfig(pHeapConfig);
+}
+
+void MainFrame::OnFileOpenPersistentHeap(wxCommandEvent& event)
+{
+ wxFileDialog Dlg(this, "Choose a file", "", "", "*.*", wxOPEN);
+ if(Dlg.ShowModal() != wxID_OK)
+ {
+ return;
+ }
+ delete m_pConfig;
+ ACE_Configuration_Heap* pHeapConfig = new ACE_Configuration_Heap;
+ pHeapConfig->open(Dlg.GetFilename());
+ SetNewConfig(pHeapConfig);
+}
+
+void MainFrame::OnFileOpenRegistry(wxCommandEvent& event)
+{
+#if defined (ACE_WIN32)
+ wxTextEntryDialog Dlg(this, "Enter Root:");
+ if(Dlg.ShowModal() != wxID_OK)
+ {
+ return;
+ }
+ HKEY Root = ACE_Configuration_Win32Registry::resolve_key(HKEY_LOCAL_MACHINE, Dlg.GetValue(), 0);
+ ACE_Configuration_Win32Registry* pWin32Reg = new ACE_Configuration_Win32Registry(Root);;
+ delete m_pConfig;
+ SetNewConfig(pWin32Reg);
+#endif
+}
+
+void MainFrame::OnFileExport(wxCommandEvent& event)
+{
+ wxFileDialog Dlg(this, "Enter Filename:", "", "", "*.*",0);
+ if(Dlg.ShowModal() != wxID_OK)
+ {
+ return;
+ }
+ m_pConfig->export_config(Dlg.GetFilename());
+}
+
+void MainFrame::OnFileImport(wxCommandEvent& event)
+{
+ wxFileDialog Dlg(this, "Choose a file", "", "", "*.*", wxOPEN);
+ if(Dlg.ShowModal() != wxID_OK)
+ {
+ return;
+ }
+ m_pConfig->import_config(Dlg.GetFilename());
+ SetNewConfig(m_pConfig);
+}
+
+void MainFrame::SetNewConfig(ACE_Configuration* pConfig)
+{
+ m_pConfig = pConfig;
+ m_pListCtrl->ChangeConfig(pConfig);
+ m_pTreeCtrl->ChangeConfig(pConfig);
+}
+
diff --git a/ACE/examples/ConfigViewer/MainFrame.h b/ACE/examples/ConfigViewer/MainFrame.h
new file mode 100644
index 00000000000..1ae7725fe80
--- /dev/null
+++ b/ACE/examples/ConfigViewer/MainFrame.h
@@ -0,0 +1,72 @@
+/* -*- C++ -*- */
+// $Id$
+
+#ifndef _ConfigurationViewer_MainFrame_H
+#define _ConfigurationViewer_MainFrame_H
+
+class ConfigTreeCtrl;
+class ValueListCtrl;
+
+enum
+{
+ // menu items
+ QUIT = 1,
+ ABOUT,
+ FILE_NEW_PERSISTENT_HEAP,
+ FILE_NEW_TRANSIENT_HEAP,
+ FILE_OPEN_PERSISTENT_HEAP,
+ FILE_OPEN_REGISTRY,
+ FILE_EXPORT,
+ FILE_IMPORT,
+ LEFT_SASH,
+ FRAME_TREE
+};
+
+
+class MainFrame : public wxFrame
+{
+public:
+ ///////////////////////////////////////////
+ // Initializers
+ ///////////////////////////////////////////
+ MainFrame(const wxString& title, const wxPoint& pos, const wxSize& size);
+ virtual ~MainFrame();
+
+ ///////////////////////////////////////////
+ // Methods
+ ///////////////////////////////////////////
+ static MainFrame* Instance();
+ void OnQuit(wxCommandEvent& event);
+ void OnAbout(wxCommandEvent& event);
+ void OnFileNewPersistentHeap(wxCommandEvent& event);
+ void OnFileNewTransientHeap(wxCommandEvent& event);
+ void OnFileOpenPersistentHeap(wxCommandEvent& event);
+ void OnFileOpenRegistry(wxCommandEvent& event);
+ void OnFileExport(wxCommandEvent& event);
+ void OnFileImport(wxCommandEvent& event);
+ void OnSize(wxSizeEvent& event);
+
+ ///////////////////////////////////////////
+ // Attribute Accessors
+ ///////////////////////////////////////////
+ ACE_Configuration* GetpConfig() {return m_pConfig;};
+protected:
+ // Not Used
+ MainFrame(const MainFrame& RHS);
+ const MainFrame& operator=(const MainFrame& RHS);
+
+ // Operations
+ void SetNewConfig(ACE_Configuration* pConfig);
+
+ // Attributes
+ wxSplitterWindow* m_pSplitter;
+ ConfigTreeCtrl* m_pTreeCtrl;
+ ValueListCtrl* m_pListCtrl;
+private:
+ DECLARE_EVENT_TABLE()
+ ACE_Configuration* m_pConfig;
+ static MainFrame* m_pInstance;
+};
+
+#endif
+
diff --git a/ACE/examples/ConfigViewer/README b/ACE/examples/ConfigViewer/README
new file mode 100644
index 00000000000..1f83c2dc848
--- /dev/null
+++ b/ACE/examples/ConfigViewer/README
@@ -0,0 +1,74 @@
+Configuration Viewer 1.0
+========================
+
+This is something I quickly threw together to allow GUI editing of
+ACE_Configuration files. I thought it would be useful and serve as a
+better example of how to use ACE_Configuration. I developed this under
+Windows 2000, but it should easily port to any platform that wxWindows
+supports (see http://www.wxwindows.org.).
+
+==============
+ Usage
+==============
+All functionality is delivered through the file menu and right mouse button
+context menus. The file menu lets you create the different types of
+ACE_Configurations such as a transient heap, persistent heap or Win32
+Registry heap. A new persistent heap may be created, or an older one
+may be opened. The win32 registry will require you to enter the path
+from HKEY_LOCAL_MACHINE that you want to open. For example: "Software/TAO"
+would set the Win32Registry's root to HKEY_LOCAL_MACHINE/Software/TAO.
+Note that this quick implementation loads the entire tree, so if you
+enter "Software" it may take a minute to load up - beware! Next you
+may import or export entries from a heap to an INI file using the
+Import/Export file commands.
+
+The right mouse button opens up a context menu in both the tree control
+and the list control.
+From the tree context menu, you can:
+1) Create new keys (these hold name/value pairs)
+2) Create new string values
+3) Create new integer values
+4) Delete a key (beware, everything beneath it will be removed as well)
+
+From the list control context menu, you can:
+1) Modify a the value of an entry
+2) Delete the entry
+3) Rename the entry
+
+Known Bugs/Issues:
+*) You cannot enter/edit binary types
+*) Adding a new string/integer value with the same name as an existing
+ entry will overwrite the existing entry without warning. I think there
+ is a memory leak that occurs as well.
+*) You can add entries to the root key, but they will not be imported
+ or exported. I think this is by design and the GUI should prevent
+ this. I need to investigate this further.
+*) The entire configuration file is loaded into the tree when it is opened.
+ For large configurations, this may take a while. A good improvement
+ would be to load items as the user expands them.
+*) At the time of this writing, there is a nasty bug in
+ ACE_Configuration_Heap that has to do with changing the value
+ of an existing entry. I have submitted a patch to fix this, but
+ it may not go in until 5.1.3 (current version is 5.1.2). I strongly
+ recommend that you get the patch/newer version!
+*) Renaming of Keys is not supported. This requires an enhancement to
+ ACE_Configuration first.
+*) No makefiles for other platforms exist, can you donate one?
+*) This has only been tested for non MFC DLL builds of ACE, it
+ should work fine in the other configurations, but I haven't tested it.
+
+=============================================
+
+This was developed using:
+*) wxWindows 2.1.15
+*) ACE 5.0.16 + My patch to fix a bug in ACE_Configuration_Heap
+*) Windows 2000
+*) MSVC 6.0 + SP3
+
+If you have any questions or comments, please send me an email. I really
+enjoy hearing about others that find this contribution useful!
+
+Chris Hafey
+May 2, 2000
+chris@stentorsoft.com
+
diff --git a/ACE/examples/ConfigViewer/ValueDlg.cpp b/ACE/examples/ConfigViewer/ValueDlg.cpp
new file mode 100644
index 00000000000..16ec9c34b22
--- /dev/null
+++ b/ACE/examples/ConfigViewer/ValueDlg.cpp
@@ -0,0 +1,63 @@
+// $Id$
+#include "stdafx.h"
+#include "ValueDlg.h"
+
+ValueDlg::ValueDlg(wxWindow* pParent, bool String)
+: wxDialog(pParent, -1, String ? "New String" : "New Value", wxDefaultPosition, wxSize(300,140))
+{
+ m_pName= new wxStaticText(this, -1, "Name:", wxPoint(20, 20));
+ m_pNameText = new wxTextCtrl(this, -1, "", wxPoint(60, 20), wxDefaultSize, 0, wxTextValidator(wxFILTER_NONE, &m_Name));
+ m_pValue = new wxStaticText(this, -1, "Value:", wxPoint(20, 50));
+ m_pValueText = new wxTextCtrl(this, -1, "", wxPoint(60, 50), wxDefaultSize, 0, wxTextValidator(String ? wxFILTER_NONE : wxFILTER_NUMERIC, &m_Value));
+ m_pOK = new wxButton(this, wxID_OK, "OK", wxPoint(60, 80));
+ m_pCancel = new wxButton(this, wxID_CANCEL, "Cancel", wxPoint(160, 80));
+}
+
+ValueDlg::ValueDlg(wxWindow* pParent, wxString& Name, wxString& Value)
+: wxDialog(pParent, -1, "Edit String", wxDefaultPosition, wxSize(300,140))
+{
+ m_Name = Name;
+ m_Value = Value;
+ m_pName= new wxStaticText(this, -1, "Name:", wxPoint(20, 20));
+ m_pNameText = new wxTextCtrl(this, -1, "", wxPoint(60, 20), wxDefaultSize, 0, wxTextValidator(wxFILTER_NONE, &m_Name));
+ m_pNameText->SetEditable(false);
+ m_pValue = new wxStaticText(this, -1, "Value:", wxPoint(20, 50));
+ m_pValueText = new wxTextCtrl(this, -1, Value, wxPoint(60, 50), wxDefaultSize, 0, wxTextValidator(wxFILTER_NONE, &m_Value));
+ m_pOK = new wxButton(this, wxID_OK, "OK", wxPoint(60, 80));
+ m_pCancel = new wxButton(this, wxID_CANCEL, "Cancel", wxPoint(160, 80));
+}
+
+ValueDlg::ValueDlg(wxWindow* pParent, wxString& Name, u_int Value)
+: wxDialog(pParent, -1, "Edit String", wxDefaultPosition, wxSize(300,140))
+{
+ m_Name = Name;
+ m_Value.sprintf("%d", Value);
+ m_pName= new wxStaticText(this, -1, "Name:", wxPoint(20, 20));
+ m_pNameText = new wxTextCtrl(this, -1, "", wxPoint(60, 20), wxDefaultSize, 0, wxTextValidator(wxFILTER_NONE, &m_Name));
+ m_pNameText->SetEditable(false);
+ m_pValue = new wxStaticText(this, -1, "Value:", wxPoint(20, 50));
+ m_pValueText = new wxTextCtrl(this, -1, m_Value, wxPoint(60, 50), wxDefaultSize, 0, wxTextValidator(wxFILTER_NUMERIC, &m_Value));
+ m_pOK = new wxButton(this, wxID_OK, "OK", wxPoint(60, 80));
+ m_pCancel = new wxButton(this, wxID_CANCEL, "Cancel", wxPoint(160, 80));
+}
+
+
+ValueDlg::~ValueDlg()
+{
+}
+
+const wxString& ValueDlg::GetName()
+{
+ return m_Name;
+}
+
+const wxString& ValueDlg::GetStringValue()
+{
+ return m_Value;
+}
+
+u_int ValueDlg::GetUINTValue()
+{
+ return atoi(m_Value);
+}
+
diff --git a/ACE/examples/ConfigViewer/ValueDlg.h b/ACE/examples/ConfigViewer/ValueDlg.h
new file mode 100644
index 00000000000..2ea4f026567
--- /dev/null
+++ b/ACE/examples/ConfigViewer/ValueDlg.h
@@ -0,0 +1,51 @@
+/* -*- C++ -*- */
+// $Id$
+
+#ifndef _ConfigurationViewer_ValueDlg_H
+#define _ConfigurationViewer_ValueDlg_H
+
+class ValueDlg : public wxDialog
+{
+public:
+ ///////////////////////////////////////////
+ // Initializers
+ ///////////////////////////////////////////
+ ValueDlg(wxWindow* pParent, bool String);
+ // New Value Ctor
+ ValueDlg(wxWindow* pParent, wxString& Name, wxString& Value);
+ // Edit String Ctor
+ ValueDlg(wxWindow* pParent, wxString& Name, u_int Value);
+ // Edit UINT Ctor
+ virtual ~ValueDlg();
+
+ ///////////////////////////////////////////
+ // Methods
+ ///////////////////////////////////////////
+ const wxString& GetName();
+ const wxString& GetStringValue();
+ u_int GetUINTValue();
+
+ ///////////////////////////////////////////
+ // Attribute Accessors
+ ///////////////////////////////////////////
+ wxButton* m_pOK;
+ wxButton* m_pCancel;
+ wxStaticText* m_pName;
+ wxTextCtrl* m_pNameText;
+ wxStaticText* m_pValue;
+ wxTextCtrl* m_pValueText;
+protected:
+ // Not Used
+ ValueDlg(const ValueDlg& RHS);
+ const ValueDlg& operator=(const ValueDlg& RHS);
+
+ wxString m_Name;
+ wxString m_Value;
+ u_int m_UINTValue;
+
+private:
+
+};
+
+#endif
+
diff --git a/ACE/examples/ConfigViewer/ValueListCtrl.cpp b/ACE/examples/ConfigViewer/ValueListCtrl.cpp
new file mode 100644
index 00000000000..93c9af14fcb
--- /dev/null
+++ b/ACE/examples/ConfigViewer/ValueListCtrl.cpp
@@ -0,0 +1,227 @@
+// $Id$
+#include "stdafx.h"
+#include "ValueListCtrl.h"
+#include "MainFrame.h"
+#include "ValueDlg.h"
+
+
+enum {VALUEMODIFY=200, VALUEDELETE, VALUERENAME};
+
+BEGIN_EVENT_TABLE(ValueListCtrl, wxListCtrl)
+ EVT_RIGHT_DOWN(ValueListCtrl::OnRightDown)
+ EVT_MENU(VALUEMODIFY, ValueListCtrl::OnModify)
+ EVT_MENU(VALUEDELETE, ValueListCtrl::OnDelete)
+ EVT_MENU(VALUERENAME, ValueListCtrl::OnRename)
+END_EVENT_TABLE()
+
+
+ValueListCtrl::ValueListCtrl(wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style, const wxValidator& validator, const wxString& name)
+: wxListCtrl(parent, id, pos, size, style | wxLC_REPORT | wxLC_SINGLE_SEL, validator, name)
+{
+ InsertColumn(0, "Name");
+ InsertColumn(1, "Type");
+ InsertColumn(2, "Data");
+}
+
+ValueListCtrl::~ValueListCtrl()
+{
+}
+
+void ValueListCtrl::DisplaySection(const ACE_Configuration_Section_Key& Key)
+{
+ m_Key = Key;
+ DeleteAllItems();
+ m_pConfig = MainFrame::Instance()->GetpConfig();
+ ACE_TString Name;
+ int Index = 0;
+ ACE_Configuration::VALUETYPE Type;
+ ACE_TString StringValue;
+ u_int UINTValue;
+ while(!m_pConfig->enumerate_values(Key, Index, Name, Type))
+ {
+ int Row = InsertItem(0, Name.fast_rep());
+ switch(Type)
+ {
+ case ACE_Configuration::STRING:
+ SetItem(Row, 1, "String");
+ m_pConfig->get_string_value(Key, Name.fast_rep(), StringValue);
+ SetItem(Row, 2, StringValue.fast_rep());
+ break;
+ case ACE_Configuration::INTEGER:
+ {
+ SetItem(Row, 1, "Integer");
+ m_pConfig->get_integer_value(Key, Name.fast_rep(), UINTValue);
+ wxString Text;
+ Text.sprintf("%d", UINTValue);
+ SetItem(Row, 2, Text);
+ }
+ break;
+ case ACE_Configuration::BINARY:
+ SetItem(Row, 1, "Binary");
+ break;
+ }
+ SetItemData(Row, Type);
+ ++Index;
+ }
+}
+
+long ValueListCtrl::GetSelectedItem()
+{
+ return GetNextItem(-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
+}
+
+void ValueListCtrl::SelectItem(long ItemID)
+{
+ // XXX Something isn't right here... When I use a mask it doesn't work at
+ // all someone explain..
+ long State = wxLIST_STATE_SELECTED | wxLIST_STATE_FOCUSED;
+ SetItemState(ItemID, State, State);
+}
+
+void ValueListCtrl::OnRightDown(wxMouseEvent& event)
+{
+ int Flags = wxLIST_HITTEST_ONITEM;
+ long ItemID = HitTest(wxPoint(event.m_x, event.m_y), Flags);
+ if(ItemID < 0)
+ {
+ return;
+ }
+ SelectItem(ItemID);
+
+ wxMenu* pMenu = new wxMenu;
+ pMenu->Append(VALUEMODIFY, "Modify");
+ pMenu->AppendSeparator();
+ pMenu->Append(VALUEDELETE, "Delete");
+ pMenu->Append(VALUERENAME, "Rename");
+ PopupMenu(pMenu, event.m_x, event.m_y);
+ delete pMenu;
+}
+
+void ValueListCtrl::OnModify(wxCommandEvent& event)
+{
+ long Item = GetSelectedItem();
+ if(Item == -1)
+ {
+ return ;
+ }
+ wxListItem ListItem;
+ ACE_Configuration::VALUETYPE Type = (ACE_Configuration::VALUETYPE)GetItemData(Item);
+ wxString Name = GetItemText(Item);
+
+ switch(Type)
+ {
+ case ACE_Configuration::STRING:
+ {
+ ACE_TString Value;
+ m_pConfig->get_string_value(m_Key, Name, Value);
+ wxString ValueText(Value.fast_rep());
+ ValueDlg Dlg(this, Name, ValueText);
+ if(Dlg.ShowModal() != wxID_OK)
+ {
+ return;
+ }
+
+ Value = (const char*)Dlg.GetStringValue();
+ m_pConfig->set_string_value(m_Key, Name, Value);
+ }
+ break;
+ case ACE_Configuration::INTEGER:
+ {
+ u_int Value;
+ m_pConfig->get_integer_value(m_Key, Name, Value);
+ ValueDlg Dlg(this, Name, Value);
+ if(Dlg.ShowModal() != wxID_OK)
+ {
+ return;
+ }
+
+ Value = Dlg.GetUINTValue();
+ m_pConfig->set_integer_value(m_Key, Name, Value);
+
+ }
+ break;
+ case ACE_Configuration::BINARY:
+ {
+ wxMessageBox("Binary modification not supported (why don't you implement it?)");
+ //assert(0);
+ }
+ break;
+ }
+ DisplaySection(m_Key);
+}
+
+void ValueListCtrl::OnDelete(wxCommandEvent& event)
+{
+ wxMessageDialog Dlg(this, "Are you sure you want to delete this value?", "Confirm Value Delete", wxYES_NO | wxICON_EXCLAMATION );
+ if(Dlg.ShowModal() != wxID_YES)
+ {
+ return;
+ }
+ long Item = GetSelectedItem();
+ if(Item == -1)
+ {
+ return ;
+ }
+ wxString Text = GetItemText(Item);
+ m_pConfig->remove_value(m_Key, Text);
+ DeleteItem(Item);
+}
+
+void ValueListCtrl::OnRename(wxCommandEvent& event)
+{
+ long Item = GetSelectedItem();
+ if(Item == -1)
+ {
+ return ;
+ }
+ wxListItem ListItem;
+ ACE_Configuration::VALUETYPE Type = (ACE_Configuration::VALUETYPE)GetItemData(Item);
+ wxString Name = GetItemText(Item);
+ wxString Message;
+ Message.sprintf("Enter new name for '%s'", Name);
+ wxTextEntryDialog Dlg(this, Message, "Please enter text", Name);
+ if(Dlg.ShowModal() != wxID_OK)
+ {
+ return;
+ }
+ wxString NewName = Dlg.GetValue();
+ if(NewName == Name)
+ {
+ return;
+ }
+
+ // XXX Check to see if an entry with this new name already exists
+
+ switch(Type)
+ {
+ case ACE_Configuration::STRING:
+ {
+ ACE_TString Value;
+ m_pConfig->get_string_value(m_Key, Name, Value);
+ m_pConfig->set_string_value(m_Key, NewName, Value);
+ }
+ break;
+ case ACE_Configuration::INTEGER:
+ {
+ u_int Value;
+ m_pConfig->get_integer_value(m_Key, Name, Value);
+ m_pConfig->set_integer_value(m_Key, NewName, Value);
+ }
+ break;
+ case ACE_Configuration::BINARY:
+ {
+ wxMessageBox("Rename binary not supported (Why don't you implement it?)");
+ assert(0);
+ }
+ }
+ m_pConfig->remove_value(m_Key, Name);
+ DisplaySection(m_Key);
+}
+
+void ValueListCtrl::ChangeConfig(ACE_Configuration* pConfig)
+{
+ m_pConfig = pConfig;
+ DisplaySection(pConfig->root_section());
+}
+
+
diff --git a/ACE/examples/ConfigViewer/ValueListCtrl.h b/ACE/examples/ConfigViewer/ValueListCtrl.h
new file mode 100644
index 00000000000..ce802e67e96
--- /dev/null
+++ b/ACE/examples/ConfigViewer/ValueListCtrl.h
@@ -0,0 +1,47 @@
+/* -*- C++ -*- */
+// $Id$
+
+#ifndef _ConfigurationViewer_ValueListCtrl_H
+#define _ConfigurationViewer_ValueListCtrl_H
+
+class ValueListCtrl : public wxListCtrl
+{
+public:
+ ///////////////////////////////////////////
+ // Initializers
+ ///////////////////////////////////////////
+ ValueListCtrl(wxWindow* parent, wxWindowID id, const wxPoint& pos = wxDefaultPosition,
+ const wxSize& size = wxDefaultSize, long style = wxLC_ICON,
+ const wxValidator& validator = wxDefaultValidator,
+ const wxString& name = "listCtrl");
+ virtual ~ValueListCtrl();
+
+ ///////////////////////////////////////////
+ // Methods
+ ///////////////////////////////////////////
+ void DisplaySection(const ACE_Configuration_Section_Key& Key);
+ long GetSelectedItem();
+ void SelectItem(long ItemID);
+ void OnRightDown(wxMouseEvent& event);
+ void OnModify(wxCommandEvent& event);
+ void OnDelete(wxCommandEvent& event);
+ void OnRename(wxCommandEvent& event);
+ void ChangeConfig(ACE_Configuration* pConfig);
+ ///////////////////////////////////////////
+ // Attribute Accessors
+ ///////////////////////////////////////////
+
+protected:
+ // Not Used
+ ValueListCtrl(const ValueListCtrl& RHS);
+ const ValueListCtrl& operator=(const ValueListCtrl& RHS);
+
+ DECLARE_EVENT_TABLE()
+private:
+
+ ACE_Configuration* m_pConfig;
+ ACE_Configuration_Section_Key m_Key;
+};
+
+#endif
+
diff --git a/ACE/examples/ConfigViewer/mondrian.ico b/ACE/examples/ConfigViewer/mondrian.ico
new file mode 100644
index 00000000000..2310c5d275a
--- /dev/null
+++ b/ACE/examples/ConfigViewer/mondrian.ico
Binary files differ
diff --git a/ACE/examples/ConfigViewer/mondrian.xpm b/ACE/examples/ConfigViewer/mondrian.xpm
new file mode 100644
index 00000000000..409f27a843c
--- /dev/null
+++ b/ACE/examples/ConfigViewer/mondrian.xpm
@@ -0,0 +1,44 @@
+/* XPM */
+static char *mondrian_xpm[] = {
+/* columns rows colors chars-per-pixel */
+"32 32 6 1",
+" c Black",
+". c Blue",
+"X c #00bf00",
+"o c Red",
+"O c Yellow",
+"+ c Gray100",
+/* pixels */
+" ",
+" oooooo +++++++++++++++++++++++ ",
+" oooooo +++++++++++++++++++++++ ",
+" oooooo +++++++++++++++++++++++ ",
+" oooooo +++++++++++++++++++++++ ",
+" oooooo +++++++++++++++++++++++ ",
+" oooooo +++++++++++++++++++++++ ",
+" oooooo +++++++++++++++++++++++ ",
+" ",
+" ++++++ ++++++++++++++++++ .... ",
+" ++++++ ++++++++++++++++++ .... ",
+" ++++++ ++++++++++++++++++ .... ",
+" ++++++ ++++++++++++++++++ .... ",
+" ++++++ ++++++++++++++++++ .... ",
+" ++++++ ++++++++++++++++++ ",
+" ++++++ ++++++++++++++++++ ++++ ",
+" ++++++ ++++++++++++++++++ ++++ ",
+" ++++++ ++++++++++++++++++ ++++ ",
+" ++++++ ++++++++++++++++++ ++++ ",
+" ++++++ ++++++++++++++++++ ++++ ",
+" ++++++ ++++++++++++++++++ ++++ ",
+" ++++++ ++++++++++++++++++ ++++ ",
+" ++++++ ++++++++++++++++++ ++++ ",
+" ++++++ ++++++++++++++++++ ++++ ",
+" ++++++ ++++ ",
+" ++++++ OOOOOOOOOOOO XXXXX ++++ ",
+" ++++++ OOOOOOOOOOOO XXXXX ++++ ",
+" ++++++ OOOOOOOOOOOO XXXXX ++++ ",
+" ++++++ OOOOOOOOOOOO XXXXX ++++ ",
+" ++++++ OOOOOOOOOOOO XXXXX ++++ ",
+" ++++++ OOOOOOOOOOOO XXXXX ++++ ",
+" "
+};
diff --git a/ACE/examples/ConfigViewer/stdafx.cpp b/ACE/examples/ConfigViewer/stdafx.cpp
new file mode 100644
index 00000000000..0c0c239bca0
--- /dev/null
+++ b/ACE/examples/ConfigViewer/stdafx.cpp
@@ -0,0 +1,3 @@
+// $Id$
+#include "stdafx.h"
+
diff --git a/ACE/examples/ConfigViewer/stdafx.h b/ACE/examples/ConfigViewer/stdafx.h
new file mode 100644
index 00000000000..565059d0dd3
--- /dev/null
+++ b/ACE/examples/ConfigViewer/stdafx.h
@@ -0,0 +1,16 @@
+/* -*- C++ -*- */
+// $Id$
+
+#include "ace/ace.h"
+#include "ace/os.h"
+#include "ace/Configuration.h"
+#include "wx/wxprec.h"
+#include "wx/laywin.h"
+#include "wx/treectrl.h"
+#include "wx/listctrl.h"
+#include "wx/splitter.h"
+
+
+
+
+
diff --git a/ACE/examples/Connection/Makefile.am b/ACE/examples/Connection/Makefile.am
new file mode 100644
index 00000000000..8aa21d598ff
--- /dev/null
+++ b/ACE/examples/Connection/Makefile.am
@@ -0,0 +1,15 @@
+## Process this file with automake to create Makefile.in
+##
+## $Id$
+##
+## This file was generated by MPC. Any changes made directly to
+## this file will be lost the next time it is generated.
+##
+## MPC Command:
+## /acebuilds/ACE_wrappers-repository/bin/mwc.pl -include /acebuilds/MPC/config -include /acebuilds/MPC/templates -feature_file /acebuilds/ACE_wrappers-repository/local.features -noreldefs -type automake -exclude build,Kokyu
+
+SUBDIRS = \
+ blocking \
+ misc \
+ non_blocking
+
diff --git a/ACE/examples/Connection/blocking/.cvsignore b/ACE/examples/Connection/blocking/.cvsignore
new file mode 100644
index 00000000000..07fde30990a
--- /dev/null
+++ b/ACE/examples/Connection/blocking/.cvsignore
@@ -0,0 +1,4 @@
+acceptor
+acceptor
+connector
+connector
diff --git a/ACE/examples/Connection/blocking/Connection_Blocking.mpc b/ACE/examples/Connection/blocking/Connection_Blocking.mpc
new file mode 100644
index 00000000000..758e2bfbf95
--- /dev/null
+++ b/ACE/examples/Connection/blocking/Connection_Blocking.mpc
@@ -0,0 +1,21 @@
+// -*- MPC -*-
+// $Id$
+
+project(*acceptor) : aceexe {
+ avoids += ace_for_tao
+ exename = acceptor
+ Source_Files {
+ SPIPE-acceptor.cpp
+ test_spipe_acceptor.cpp
+ }
+}
+
+project(*connector) : aceexe {
+ avoids += ace_for_tao
+ exename = connector
+ Source_Files {
+ SPIPE-connector.cpp
+ test_spipe_connector.cpp
+ }
+}
+
diff --git a/ACE/examples/Connection/blocking/Makefile.am b/ACE/examples/Connection/blocking/Makefile.am
new file mode 100644
index 00000000000..a12eab920b8
--- /dev/null
+++ b/ACE/examples/Connection/blocking/Makefile.am
@@ -0,0 +1,60 @@
+## Process this file with automake to create Makefile.in
+##
+## $Id$
+##
+## This file was generated by MPC. Any changes made directly to
+## this file will be lost the next time it is generated.
+##
+## MPC Command:
+## /acebuilds/ACE_wrappers-repository/bin/mwc.pl -include /acebuilds/MPC/config -include /acebuilds/MPC/templates -feature_file /acebuilds/ACE_wrappers-repository/local.features -noreldefs -type automake -exclude build,Kokyu
+
+ACE_BUILDDIR = $(top_builddir)
+ACE_ROOT = $(top_srcdir)
+
+noinst_PROGRAMS =
+
+## Makefile.Connection_Blocking_Acceptor.am
+
+if !BUILD_ACE_FOR_TAO
+noinst_PROGRAMS += acceptor
+
+acceptor_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+acceptor_SOURCES = \
+ SPIPE-acceptor.cpp \
+ test_spipe_acceptor.cpp \
+ SPIPE-acceptor.h
+
+acceptor_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+endif !BUILD_ACE_FOR_TAO
+
+## Makefile.Connection_Blocking_Connector.am
+
+if !BUILD_ACE_FOR_TAO
+noinst_PROGRAMS += connector
+
+connector_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+connector_SOURCES = \
+ SPIPE-connector.cpp \
+ test_spipe_connector.cpp \
+ SPIPE-connector.h
+
+connector_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+endif !BUILD_ACE_FOR_TAO
+
+## Clean up template repositories, etc.
+clean-local:
+ -rm -f *~ *.bak *.rpo *.sym lib*.*_pure_* core core.*
+ -rm -f gcctemp.c gcctemp so_locations *.ics
+ -rm -rf cxx_repository ptrepository ti_files
+ -rm -rf templateregistry ir.out
+ -rm -rf ptrepository SunWS_cache Templates.DB
diff --git a/ACE/examples/Connection/blocking/README b/ACE/examples/Connection/blocking/README
new file mode 100644
index 00000000000..c7763e3ed04
--- /dev/null
+++ b/ACE/examples/Connection/blocking/README
@@ -0,0 +1,36 @@
+Presently, this directory contains only one example application for
+SPIPEs. The test source code is contained in SPIPE-acceptor.h and
+SPIPE-connector.h.
+
+The SPIPE-acceptor example illustrates how named pipes are used on NT.
+Once the server establishes a connection to a single client, it spawns
+a thread pool to handle incoming requests via the proactor event loop.
+That is, a separate thread from the pool is used to process each
+message sent by a client. The size of the thread pool can be
+specified by command-line arguments. This example leverages the
+queueing performed by the NT kernel to trivially implement a thread
+pool architecture.
+
+test_spipe_acceptor has the following command-line arguments:
+
+test_spipe_acceptor -t <threads>
+
+<threads> specifies the size of the thread-pool running in the
+proactor event loop.
+
+Here's how to run the tests:
+
+% test_spipe_acceptor -t 1000000
+starting up daemon test_sock_acceptor
+Opening acepipe
+hello
+
+% test_spipe_connector
+starting up daemon test_sock_connector
+Opening acepipe
+activating 5
+
+please enter input..: hello
+
+There are a number of other options that you can provide. Please see
+the source code for details.
diff --git a/ACE/examples/Connection/blocking/SPIPE-acceptor.cpp b/ACE/examples/Connection/blocking/SPIPE-acceptor.cpp
new file mode 100644
index 00000000000..8885b0353cd
--- /dev/null
+++ b/ACE/examples/Connection/blocking/SPIPE-acceptor.cpp
@@ -0,0 +1,224 @@
+// $Id$
+
+#if !defined (SPIPE_ACCEPTOR_C)
+#define SPIPE_ACCEPTOR_C
+
+#include "ace/OS_NS_string.h"
+#include "ace/SPIPE_Addr.h"
+#include "ace/SPIPE_Acceptor.h"
+#include "ace/Proactor.h"
+#include "ace/Get_Opt.h"
+#include "ace/Signal.h"
+#include "SPIPE-acceptor.h"
+
+ACE_RCSID(blocking, SPIPE_acceptor, "$Id$")
+
+#if ((defined (ACE_WIN32) && !defined (ACE_HAS_WINCE)) || (defined (ACE_HAS_AIO_CALLS)))
+
+Svc_Handler::Svc_Handler (void)
+ : mb_ (BUFSIZ + 1)
+{
+ // An extra byte for null termination.
+ this->mb_.size (BUFSIZ);
+}
+
+Svc_Handler::~Svc_Handler (void)
+{
+}
+
+int
+Svc_Handler::open (void *)
+{
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("client connected on handle %d\n"),
+ this->peer ().get_handle ()));
+ if (this->ar_.open (*this,
+ this->peer ().get_handle ()) == -1)
+ return -1;
+ return this->ar_.read (this->mb_,
+ this->mb_.size ());
+}
+
+void
+Svc_Handler::handle_read_stream (const ACE_Asynch_Read_Stream::Result &result)
+{
+ if (result.success () && result.bytes_transferred () > 0)
+ {
+ result.message_block ().rd_ptr ()[result.message_block ().length ()] = '\0';
+
+ // Print out the message received from the server.
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("(%t) message size %d.\n"),
+ result.message_block ().length ()));
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("%C"),
+ result.message_block ().rd_ptr ()));
+ // Reset the message block here to make sure multiple writes to
+ // the pipe don't keep appending to the message_block!
+ this->mb_.reset ();
+
+ this->ar_.read (this->mb_, this->mb_.size ());
+ }
+ else
+ ACE_Proactor::end_event_loop ();
+}
+
+IPC_Server::IPC_Server (void)
+ : n_threads_ (1),
+ shutdown_ (0)
+{
+ ACE_OS::strcpy (rendezvous_, ACE_TEXT ("acepipe"));
+}
+
+IPC_Server::~IPC_Server (void)
+{
+}
+
+int
+IPC_Server::handle_signal (int,
+ siginfo_t *,
+ ucontext_t *)
+{
+ ACE_LOG_MSG->log (LM_INFO, ACE_TEXT ("IPC_Server::handle_signal().\n"));
+
+ // Flag the main <svc> loop to shutdown.
+ this->shutdown_ = 1;
+
+ this->acceptor ().close (); // Close underlying acceptor.
+ // This should cause the <accept> to fail, which will "bounce"
+ // us out of the loop in <svc>.
+ return 0;
+}
+
+int
+IPC_Server::init (int argc, ACE_TCHAR *argv[])
+{
+ if (this->parse_args (argc, argv) == -1)
+ return -1;
+
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Opening %s\n"), rendezvous_));
+
+ // Initialize named pipe listener.
+ if (this->open (ACE_SPIPE_Addr (rendezvous_)) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("open")), 1);
+
+ // Register to receive shutdowns using this handler.
+ else if (ACE_Reactor::instance ()->register_handler
+ (SIGINT, this) == -1)
+ return -1;
+ else
+ return 0;
+}
+
+int
+IPC_Server::fini (void)
+{
+ return 0;
+}
+
+int
+IPC_Server::parse_args (int argc, ACE_TCHAR *argv[])
+{
+ ACE_LOG_MSG->open (argv[0]);
+
+ ACE_Get_Opt get_opt (argc, argv, ACE_TEXT ("ut:r:"));
+
+ for (int c; (c = get_opt ()) != -1; )
+ {
+ switch (c)
+ {
+ case 'r':
+ ACE_OS::strncpy (rendezvous_,
+ get_opt.opt_arg (),
+ sizeof (rendezvous_) / sizeof (ACE_TCHAR));
+ break;
+ case 't':
+ n_threads_ = ACE_OS::atoi (get_opt.opt_arg ());
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("%s == %d.\n"),
+ get_opt.opt_arg (),
+ n_threads_));
+ ACE_Proactor::instance (2 * n_threads_);
+ // This is a lame way to tell the proactor how many threads
+ // we'll be using.
+ break;
+ case 'u':
+ default:
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("usage: %n -t <threads>\n")
+ ACE_TEXT (" -r <rendezvous>\n")), -1);
+ break;
+ }
+ }
+
+ return 0;
+}
+
+static ACE_THR_FUNC_RETURN
+run_reactor_event_loop (void *)
+{
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("(%t) worker thread starting\n")));
+
+ ACE_Proactor::run_event_loop ();
+ return 0;
+}
+
+int
+IPC_Server::svc (void)
+{
+ // Performs the iterative server activities.
+ while (this->shutdown_ == 0)
+ {
+ Svc_Handler sh;
+
+ // Create a new SH endpoint, which performs all processing in
+ // its open() method (note no automatic restart if errno ==
+ // EINTR).
+ if (this->accept (&sh, 0) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("accept")),
+ 1);
+
+ // SH's destructor closes the stream implicitly but the
+ // listening endpoint stays open.
+ else
+ {
+ // Run single-threaded.
+ if (n_threads_ <= 1)
+ run_reactor_event_loop (0);
+ else if (ACE_Thread_Manager::instance ()->spawn_n
+ (n_threads_,
+ run_reactor_event_loop,
+ 0,
+ THR_NEW_LWP) == -1)
+ {
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("spawn_n")),
+ 1);
+
+ ACE_Thread_Manager::instance ()->wait ();
+ }
+
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("(%t) main thread exiting.\n")));
+
+ // Reset the Proactor so another accept will work.
+ ACE_Proactor::reset_event_loop();
+
+ // Must use some other method now to terminate this thing
+ // instead of the ACE_Signal_Adapter just running
+ // ACE_Proactor::end_event_loop()... Since this is an
+ // ACE_Event_Handler, doesn't it seem possible to implement
+ // a handle_signal() hook, and catch the signal there?
+ }
+ }
+
+ /* NOTREACHED */
+ return 0;
+}
+
+#endif /* ACE_WIN32 || ACE_HAS_AIO_CALLS*/
+#endif /* SPIPE_ACCEPTOR_C */
+
diff --git a/ACE/examples/Connection/blocking/SPIPE-acceptor.h b/ACE/examples/Connection/blocking/SPIPE-acceptor.h
new file mode 100644
index 00000000000..546941c48fb
--- /dev/null
+++ b/ACE/examples/Connection/blocking/SPIPE-acceptor.h
@@ -0,0 +1,79 @@
+/* -*- C++ -*- */
+// $Id$
+
+#ifndef SP_ACCEPTOR_H
+#define SP_ACCEPTOR_H
+
+#include "ace/Svc_Handler.h"
+#include "ace/Service_Config.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/Acceptor.h"
+#include "ace/SPIPE_Stream.h"
+#include "ace/SPIPE_Acceptor.h"
+#include "ace/Asynch_IO.h"
+
+// This only works on Win32 platforms and on Unix platforms
+// supporting POSIX aio calls.
+#if ((defined (ACE_WIN32) && !defined (ACE_HAS_WINCE)) || (defined (ACE_HAS_AIO_CALLS)))
+
+// This is the class that does the work once the ACE_Oneshot_Acceptor
+// has accepted a connection.
+
+class Svc_Handler : public ACE_Svc_Handler <ACE_SPIPE_STREAM, ACE_NULL_SYNCH>, public ACE_Handler
+{
+public:
+ Svc_Handler (void);
+ ~Svc_Handler (void);
+
+ virtual int open (void *);
+
+ virtual void handle_read_stream (const ACE_Asynch_Read_Stream::Result &result);
+ // This is called when asynchronous read from the socket complete
+ // Handle data from the client.
+
+private:
+ ACE_Asynch_Read_Stream ar_;
+ ACE_Message_Block mb_;
+};
+
+class IPC_Server : public ACE_Oneshot_Acceptor<Svc_Handler, ACE_SPIPE_ACCEPTOR>
+{
+public:
+ IPC_Server (void);
+ ~IPC_Server (void);
+
+ // = Dynamic linking hooks.
+ virtual int init (int argc, ACE_TCHAR *argv[]);
+ // Initialize the network server.
+
+ virtual int fini (void);
+ // Close down the server.
+
+ virtual int svc (void);
+ // Run the interative service.
+
+private:
+ int parse_args (int argc, ACE_TCHAR *argv[]);
+ // Parse command-line arguments.
+
+ int n_threads_;
+ // Size of thread pool to use.
+
+ ACE_TCHAR rendezvous_[MAXPATHLEN + 1];
+ // Meeting place for pipe.
+
+ int shutdown_;
+ // Keeps track of when we shut down due to receipt of the SIGINT
+ // signal.
+
+ int handle_signal (int signum, siginfo_t *, ucontext_t *);
+ // Signal handler method.
+};
+
+#endif /* ACE_WIN32 || ACE_HAS_AIO_CALLS*/
+#endif /* SP_ACCEPTOR_H */
+
diff --git a/ACE/examples/Connection/blocking/SPIPE-connector.cpp b/ACE/examples/Connection/blocking/SPIPE-connector.cpp
new file mode 100644
index 00000000000..6618b64f0cb
--- /dev/null
+++ b/ACE/examples/Connection/blocking/SPIPE-connector.cpp
@@ -0,0 +1,219 @@
+// $Id$
+
+#if !defined (SPIPE_CONNECTOR_C)
+
+#define SPIPE_CONNECTOR_C
+
+#include "ace/OS_NS_string.h"
+#include "ace/SPIPE_Addr.h"
+#include "ace/SPIPE_Connector.h"
+#include "ace/Proactor.h"
+#include "ace/Get_Opt.h"
+#include "ace/OS_NS_unistd.h"
+#include "SPIPE-connector.h"
+
+ACE_RCSID(blocking, SPIPE_connector, "$Id$")
+
+Peer_Handler::Peer_Handler (int iterations)
+ : iterations_ (iterations)
+{
+}
+
+Peer_Handler::~Peer_Handler (void)
+{
+}
+
+int
+Peer_Handler::open (void *)
+{
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("activating %d\n"), this->get_handle ()));
+
+ // If iterations_ has not been set, read from stdin.
+ if (iterations_ == 0)
+ {
+ this->display_menu ();
+ if (ACE_Event_Handler::register_stdin_handler
+ (this,
+ ACE_Reactor::instance (),
+ ACE_Thread_Manager::instance ()) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("register_stdin_handler")),
+ -1);
+ else
+ return 0;
+ }
+ else // If iterations_ has been set, send iterations_ buffers.
+ {
+ const char *buffer =
+ "Oh give me a home\n"
+ "Where the buffalo roam,\n"
+ "And the deer and the antelope play.\n"
+ "Where seldom is heard\n"
+ "A discouraging word,\n"
+ "And the skies are not cloudy all day.\n";
+ int length = ACE_OS::strlen (buffer);
+
+ while (iterations_-- > 0
+ && this->peer ().send_n (buffer,
+ length) == length)
+ continue;
+
+ this->peer ().close ();
+ ACE_Reactor::instance ()->end_reactor_event_loop();
+ return 0;
+ }
+}
+
+int
+Peer_Handler::handle_input (ACE_HANDLE)
+{
+ char buf[BUFSIZ];
+
+ ssize_t n = ACE_OS::read (ACE_STDIN,
+ buf,
+ sizeof buf);
+
+ if (n > 0)
+ if (this->peer ().send (buf, n) != n)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("write failed")),
+ -1);
+ else if (n == 0) // Explicitly close the connection.
+ {
+ if (this->peer ().close () == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("close")),
+ 1);
+ return -1;
+ }
+ else
+ this->display_menu ();
+ return 0;
+}
+
+int
+Peer_Handler::handle_close (ACE_HANDLE,
+ ACE_Reactor_Mask)
+{
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Shutting down\n")));
+ return 0;
+}
+
+ACE_HANDLE
+Peer_Handler::get_handle (void) const
+{
+ return this->peer ().get_handle ();
+}
+
+void
+Peer_Handler::display_menu (void)
+{
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\nplease enter input..: ")));
+}
+
+IPC_Client::IPC_Client (void)
+ : iterations_ (0),
+ done_handler_ (ACE_Sig_Handler_Ex (ACE_Proactor::end_event_loop))
+{
+ ACE_OS::strcpy (rendezvous_, ACE_TEXT ("acepipe"));
+}
+
+IPC_Client::~IPC_Client (void)
+{
+}
+
+// Dynamic linking hooks.
+
+int
+IPC_Client::init (int argc, ACE_TCHAR *argv[])
+{
+ if (this->parse_args (argc, argv) == -1)
+ return -1;
+ // Handle signals through the ACE_Reactor.
+ else if (ACE_Reactor::instance ()->register_handler
+ (SIGINT,
+ &this->done_handler_) == -1)
+ return -1;
+
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Opening %s\n"), rendezvous_));
+
+ Peer_Handler *ph;
+
+ ACE_NEW_RETURN (ph,
+ Peer_Handler (iterations_),
+ -1);
+
+ // Connect to the peer, reusing the local addr if necessary.
+ if (this->connect (ph,
+ ACE_SPIPE_Addr (rendezvous_),
+ ACE_Synch_Options::defaults,
+ ACE_sap_any_cast (ACE_SPIPE_Addr &),
+ 0,
+ O_RDWR | FILE_FLAG_OVERLAPPED,
+ 0) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("connect")),
+ -1);
+
+ return 0;
+}
+
+int
+IPC_Client::fini (void)
+{
+ return 0;
+}
+
+int
+IPC_Client::svc (void)
+{
+ ACE_Reactor::instance ()->run_reactor_event_loop ();
+ return 0;
+}
+
+int
+IPC_Client::handle_close (ACE_HANDLE,
+ ACE_Reactor_Mask)
+{
+ return 0;
+}
+
+int
+IPC_Client::parse_args (int argc, ACE_TCHAR *argv[])
+{
+ ACE_LOG_MSG->open (argv[0]);
+
+ ACE_Get_Opt get_opt (argc, argv, ACE_TEXT ("ui:r:"));
+
+ for (int c; (c = get_opt ()) != -1; )
+ {
+ switch (c)
+ {
+ case 'r':
+ ACE_OS::strncpy (rendezvous_,
+ get_opt.opt_arg (),
+ sizeof (rendezvous_) / sizeof (ACE_TCHAR));
+ break;
+ case 'i':
+ iterations_ = ACE_OS::atoi (get_opt.opt_arg ());
+ break;
+ case 'u':
+ default:
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("usage: %n -i <iterations>\n")
+ ACE_TEXT ("-r <rendezvous>\n")),
+ -1);
+ break;
+ }
+ }
+
+ return 0;
+}
+
+
+#endif /* SPIPE_CONNECTOR */
+
diff --git a/ACE/examples/Connection/blocking/SPIPE-connector.h b/ACE/examples/Connection/blocking/SPIPE-connector.h
new file mode 100644
index 00000000000..66d6ea0d1ed
--- /dev/null
+++ b/ACE/examples/Connection/blocking/SPIPE-connector.h
@@ -0,0 +1,82 @@
+/* -*- C++ -*- */
+// $Id$
+
+#ifndef SP_CONNECTOR_H
+#define SP_CONNECTOR_H
+
+#include "ace/Svc_Handler.h"
+#include "ace/Service_Config.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/SPIPE_Stream.h"
+#include "ace/Connector.h"
+#include "ace/SPIPE_Connector.h"
+#include "ace/Sig_Adapter.h"
+
+class Peer_Handler : public ACE_Svc_Handler<ACE_SPIPE_STREAM, ACE_NULL_SYNCH>
+{
+public:
+ // = Initialization
+
+ Peer_Handler (int iterations = 0);
+ // <iterations> is the number of buffers to send. If <iterations>
+ // == 0, then read from stdin.
+
+ ~Peer_Handler (void);
+
+ virtual int open (void * = 0);
+ // Activate the handler when connection is established.
+
+ // = Demultiplexing hooks.
+ virtual int handle_input (ACE_HANDLE);
+ virtual int handle_close (ACE_HANDLE handle = ACE_INVALID_HANDLE,
+ ACE_Reactor_Mask mask = ACE_Event_Handler::ALL_EVENTS_MASK);
+
+ virtual ACE_HANDLE get_handle (void) const;
+
+private:
+ void display_menu (void);
+
+ int iterations_;
+ // No. of buffers to send.
+};
+
+class IPC_Client : public ACE_Connector<Peer_Handler, ACE_SPIPE_CONNECTOR>
+{
+public:
+ // Initialization
+ IPC_Client (void);
+ ~IPC_Client (void);
+
+ // = Dynamic linking hooks.
+ virtual int init (int argc, ACE_TCHAR *argv[]);
+ // Initialize the IPC client.
+
+ virtual int fini (void);
+ // Destroy the IPC client.
+
+ virtual int svc (void);
+ // Run the svc.
+
+ virtual int handle_close (ACE_HANDLE, ACE_Reactor_Mask);
+ // Report connection errors.
+
+private:
+ int parse_args (int argc, ACE_TCHAR *argv[]);
+ // Parse command-line arguments.
+
+ int iterations_;
+ // Number of times to send a buffer.
+
+ ACE_TCHAR rendezvous_[MAXPATHLEN + 1];
+ // Meeting place for pipe.
+
+ ACE_Sig_Adapter done_handler_;
+ // Keeps track of when we shut down due to receipt of the SIGINT
+ // signal.
+};
+
+#endif /* SP_CONNECTOR_H */
diff --git a/ACE/examples/Connection/blocking/test_spipe_acceptor.cpp b/ACE/examples/Connection/blocking/test_spipe_acceptor.cpp
new file mode 100644
index 00000000000..549690ebf43
--- /dev/null
+++ b/ACE/examples/Connection/blocking/test_spipe_acceptor.cpp
@@ -0,0 +1,36 @@
+// $Id$
+
+// ACE_SPIPE Server.
+
+#include "SPIPE-acceptor.h"
+
+ACE_RCSID(blocking, test_spipe_acceptor, "$Id$")
+
+#if ((defined (ACE_WIN32) && !defined (ACE_HAS_WINCE)) || (defined (ACE_HAS_AIO_CALLS)))
+
+int
+ACE_TMAIN (int argc, ACE_TCHAR *argv[])
+{
+ // Perform Service_Config initializations
+ ACE_Service_Config daemon (argv[0]);
+
+ IPC_Server peer_acceptor;
+
+ if (peer_acceptor.init (argc, argv) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("%p\n"), ACE_TEXT ("init")), -1);
+
+ return peer_acceptor.svc ();
+}
+
+#else
+
+int
+main (int, char *[])
+{
+ ACE_DEBUG ((LM_INFO,
+ ACE_TEXT ("Asynchronous IO is unsupported.\n")));
+
+ return 0;
+}
+
+#endif
diff --git a/ACE/examples/Connection/blocking/test_spipe_connector.cpp b/ACE/examples/Connection/blocking/test_spipe_connector.cpp
new file mode 100644
index 00000000000..e10cc023a6f
--- /dev/null
+++ b/ACE/examples/Connection/blocking/test_spipe_connector.cpp
@@ -0,0 +1,21 @@
+// $Id$
+
+// ACE_SPIPE Client.
+
+#include "SPIPE-connector.h"
+
+ACE_RCSID(blocking, test_spipe_connector, "$Id$")
+
+int
+ACE_TMAIN (int argc, ACE_TCHAR *argv[])
+{
+ // Perform Service_Config initializations
+ ACE_Service_Config daemon (argv[0]);
+
+ IPC_Client peer_connector;
+
+ if (peer_connector.init (argc, argv) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("%p\n"), ACE_TEXT ("init")), -1);
+
+ return peer_connector.svc ();
+}
diff --git a/ACE/examples/Connection/misc/.cvsignore b/ACE/examples/Connection/misc/.cvsignore
new file mode 100644
index 00000000000..444ad7e1b3a
--- /dev/null
+++ b/ACE/examples/Connection/misc/.cvsignore
@@ -0,0 +1,4 @@
+handler
+handler
+test_upipe
+test_upipe
diff --git a/ACE/examples/Connection/misc/Connection_Handler.cpp b/ACE/examples/Connection/misc/Connection_Handler.cpp
new file mode 100644
index 00000000000..6abc0ee8050
--- /dev/null
+++ b/ACE/examples/Connection/misc/Connection_Handler.cpp
@@ -0,0 +1,226 @@
+// $Id$
+
+// ============================================================================
+//
+// = FILENAME
+// Connection_Handler.cpp
+//
+// = DESCRIPTION
+// This test illustrates how to use the Acceptor pattern to
+// create multiple threads, each running its own Reactor. You
+// can connect to this via telnet and keep typing until you enter
+// '^D'.
+//
+// = AUTHOR
+// Doug Schmidt
+//
+// ============================================================================
+
+#include "ace/Acceptor.h"
+#include "ace/SOCK_Acceptor.h"
+#include "ace/Service_Config.h"
+#include "ace/Thread.h"
+#include "ace/Sig_Adapter.h"
+
+#include "Connection_Handler.h"
+
+ACE_RCSID(misc, Connection_Handler, "$Id$")
+
+int
+Connection_Handler::open (void *)
+{
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("(%P|%t) in open()\n")));
+
+ // Make ourselves an Active Object.
+ return this->activate (THR_NEW_LWP | THR_DETACHED);
+}
+
+int
+Connection_Handler::close (u_long)
+{
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("(%P|%t) in close()\n")));
+
+ // Shut ourself down. Note that this doesn't destroy the thread,
+ // just the state of the object.
+ this->destroy ();
+ return 0;
+}
+
+int
+Connection_Handler::svc (void)
+{
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("(%P|%t) in svc()\n")));
+
+ this->finished_ = 0;
+
+ // Create our own personal Reactor just for this thread. Note that
+ // we create this on the stack of the thread since it's only used
+ // for the duration of this connection!
+
+ ACE_Reactor reactor;
+
+ // Each <ACE_Svc_Handler> has its own <ACE_Reactor *>. By default,
+ // this points to the <Acceptor's> Reactor. However, we can point
+ // it to our local Reactor, which is what we do in this case.
+ this->reactor (&reactor);
+
+ // Register ourselves to handle input in this thread without
+ // blocking.
+ if (this->reactor ()->register_handler
+ (this, ACE_Event_Handler::READ_MASK) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("can' (%P|%t) t register with reactor\n")),
+ -1);
+ // Schedule a timer.
+ else if (this->reactor ()->schedule_timer (this,
+ (const void *) this,
+ ACE_Time_Value (2),
+ ACE_Time_Value (2)) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("(%P|%t) can't register with reactor\n")),
+ -1);
+ else
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("(%P|%t) connected with client\n")));
+
+ // Keep looping until we receive SIGQUIT or the client shutsdown.
+
+ while (this->finished_ == 0)
+ {
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("(%P|%t) handling events\n")));
+ this->reactor ()->handle_events ();
+ }
+
+ // Cancel all pending timeouts.
+ this->reactor ()->cancel_timer (this);
+
+ // Remove ourselves from the Reactor.
+ this->reactor ()->remove_handler
+ (this, ACE_Event_Handler::READ_MASK | ACE_Event_Handler::DONT_CALL);
+
+ // Zero-out the Reactor field so it isn't accessed later on.
+ this->reactor (0);
+
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("(%P|%t) exiting svc\n")));
+ return 0;
+}
+
+int
+Connection_Handler::handle_close (ACE_HANDLE,
+ ACE_Reactor_Mask)
+{
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("(%P|%t) in handle_close \n")));
+
+ // Signal the svc() event loop to shut down.
+ this->finished_ = 1;
+ return 0;
+}
+
+int
+Connection_Handler::handle_input (ACE_HANDLE)
+{
+ char buf[BUFSIZ];
+
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("(%P|%t) handle_input\n")));
+
+ switch (this->peer ().recv (buf, sizeof buf))
+ {
+ case -1:
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("(%P|%t) %p bad read\n"),
+ ACE_TEXT ("client logger")),
+ -1);
+ case 0:
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("(%P|%t) closing log daemon (fd = %d)\n"),
+ this->get_handle ()),
+ -1);
+ default:
+ if (buf[0] == (char) EOF)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("(%P|%t) closing log daemon (fd = %d)\n"),
+ this->get_handle ()),
+ -1);
+ else
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("(%P|%t) from client: %s"), buf));
+ }
+
+ return 0;
+}
+
+int
+Connection_Handler::handle_signal (int signum,
+ siginfo_t *,
+ ucontext_t *)
+{
+ // @@ Note that this code is not portable to all OS platforms since
+ // it uses print statements within signal handler context.
+
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("received signal %S\n"), signum));
+
+ this->finished_ = 1;
+ return 0;
+}
+
+int
+Connection_Handler::handle_timeout (const ACE_Time_Value &,
+ const void *arg)
+{
+#if defined (ACE_NDEBUG)
+ ACE_UNUSED_ARG (arg);
+#endif /* ACE_NDEBUG */
+
+ ACE_ASSERT (arg == this);
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("(%P|%t) handling timeout from this = %@\n"),
+ this));
+ return 0;
+}
+
+// Define an Acceptor for the <Connection_Handler>.
+
+typedef ACE_Acceptor <Connection_Handler, ACE_SOCK_ACCEPTOR>
+ Connection_Acceptor;
+
+int
+ACE_TMAIN (int argc, ACE_TCHAR *argv[])
+{
+ ACE_Service_Config daemon (argv[0]);
+
+ u_short port = argc > 1 ? ACE_OS::atoi (argv[1]) : ACE_DEFAULT_SERVER_PORT;
+
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("(%P|%t) in main\n")));
+
+ // Acceptor factory.
+ Connection_Acceptor peer_acceptor;
+
+ // Create an adapter to end the event loop.
+ ACE_Sig_Adapter sa ((ACE_Sig_Handler_Ex) ACE_Reactor::end_event_loop);
+
+ // Register the signal handler adapter.
+ if (ACE_Reactor::instance ()->register_handler (SIGINT, &sa) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("register_handler")),
+ -1);
+
+ // Open the Acceptor.
+ else if (peer_acceptor.open (ACE_INET_Addr (port),
+ ACE_Reactor::instance ()) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("open")),
+ -1);
+
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("(%P|%t) starting up connection server\n")));
+
+ // Perform connection service until we receive SIGINT.
+
+ while (ACE_Reactor::event_loop_done() == 0)
+ ACE_Reactor::run_event_loop ();
+
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("(%P|%t) shutting down connection server\n")));
+ return 0;
+}
+
diff --git a/ACE/examples/Connection/misc/Connection_Handler.h b/ACE/examples/Connection/misc/Connection_Handler.h
new file mode 100644
index 00000000000..2e22ac8dc11
--- /dev/null
+++ b/ACE/examples/Connection/misc/Connection_Handler.h
@@ -0,0 +1,44 @@
+/* -*- C++ -*- */
+
+// $Id$
+
+#ifndef ACE_CONNECTION_HANDLER_H
+#define ACE_CONNECTION_HANDLER_H
+
+#include "ace/SOCK_Stream.h"
+#include "ace/Svc_Handler.h"
+
+class Connection_Handler : public ACE_Svc_Handler<ACE_SOCK_STREAM, ACE_NULL_SYNCH>
+{
+public:
+ virtual int open (void *);
+ // Initialize the <Connection_Handler> and make it an Active Object.
+
+ virtual int close (u_long);
+ // Terminate the <Connection_Handler>.
+
+ virtual int svc (void);
+ // Run the <Connection_Handler>'s main event loop.
+
+protected:
+ virtual int handle_close (ACE_HANDLE,
+ ACE_Reactor_Mask);
+ // Signal the Active Object to stop when called.
+
+ virtual int handle_input (ACE_HANDLE);
+ // Handle input from the client.
+
+ virtual int handle_timeout (const ACE_Time_Value &tv,
+ const void *arg);
+ // Handle timeouts.
+
+ virtual int handle_signal (int signum,
+ siginfo_t *,
+ ucontext_t *);
+ // Handle timeouts.
+
+ sig_atomic_t finished_;
+ // Keeps track of whether we're done.
+};
+
+#endif /* ACE_CONNECTION_HANDLER_H */
diff --git a/ACE/examples/Connection/misc/Connection_Misc.mpc b/ACE/examples/Connection/misc/Connection_Misc.mpc
new file mode 100644
index 00000000000..a960e604338
--- /dev/null
+++ b/ACE/examples/Connection/misc/Connection_Misc.mpc
@@ -0,0 +1,17 @@
+// -*- MPC -*-
+// $Id$
+
+project (*Handler) : aceexe {
+ exename = handler
+ Source_Files {
+ Connection_Handler.cpp
+ }
+}
+
+project (*test_upipe) : aceexe {
+ avoids += ace_for_tao
+ exename = test_upipe
+ Source_Files {
+ test_upipe.cpp
+ }
+}
diff --git a/ACE/examples/Connection/misc/Makefile.am b/ACE/examples/Connection/misc/Makefile.am
new file mode 100644
index 00000000000..ce3790d2851
--- /dev/null
+++ b/ACE/examples/Connection/misc/Makefile.am
@@ -0,0 +1,53 @@
+## Process this file with automake to create Makefile.in
+##
+## $Id$
+##
+## This file was generated by MPC. Any changes made directly to
+## this file will be lost the next time it is generated.
+##
+## MPC Command:
+## /acebuilds/ACE_wrappers-repository/bin/mwc.pl -include /acebuilds/MPC/config -include /acebuilds/MPC/templates -feature_file /acebuilds/ACE_wrappers-repository/local.features -noreldefs -type automake -exclude build,Kokyu
+
+ACE_BUILDDIR = $(top_builddir)
+ACE_ROOT = $(top_srcdir)
+
+
+## Makefile.Connection_Misc_Handler.am
+noinst_PROGRAMS = handler
+
+handler_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+handler_SOURCES = \
+ Connection_Handler.cpp \
+ Connection_Handler.h
+
+handler_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Makefile.Connection_Misc_Test_Upipe.am
+
+if !BUILD_ACE_FOR_TAO
+noinst_PROGRAMS += test_upipe
+
+test_upipe_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+test_upipe_SOURCES = \
+ test_upipe.cpp \
+ test_upipe.h
+
+test_upipe_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+endif !BUILD_ACE_FOR_TAO
+
+## Clean up template repositories, etc.
+clean-local:
+ -rm -f *~ *.bak *.rpo *.sym lib*.*_pure_* core core.*
+ -rm -f gcctemp.c gcctemp so_locations *.ics
+ -rm -rf cxx_repository ptrepository ti_files
+ -rm -rf templateregistry ir.out
+ -rm -rf ptrepository SunWS_cache Templates.DB
diff --git a/ACE/examples/Connection/misc/test_upipe.cpp b/ACE/examples/Connection/misc/test_upipe.cpp
new file mode 100644
index 00000000000..23c85b283a3
--- /dev/null
+++ b/ACE/examples/Connection/misc/test_upipe.cpp
@@ -0,0 +1,122 @@
+// $Id$
+
+// This short program illustrates in implementation of the classic
+// "bounded buffer" program using ACE_UPIPEs. This program also shows
+// how the ACE_Connector and ACE_Acceptor patterns work when used with
+// ACE_UPIPEs.
+
+#include "ace/Acceptor.h"
+#include "ace/UPIPE_Acceptor.h"
+#include "ace/UPIPE_Connector.h"
+#include "ace/Connector.h"
+#include "ace/UPIPE_Addr.h"
+
+ACE_RCSID(misc, test_upipe, "$Id$")
+
+#if defined (ACE_HAS_THREADS)
+
+#include "test_upipe.h"
+
+class Server : public ACE_Strategy_Acceptor <Server_Service, ACE_UPIPE_ACCEPTOR>
+{
+ // = TITLE
+ // Defines the interface for a factory that accepts connections
+ // and creates/activates Server_Service objects.
+public:
+ Server (ACE_Thread_Manager *thr_mgr,
+ ACE_Reactor *reactor)
+ : reactor_ (reactor),
+ thr_mgr_ (thr_mgr)
+ {
+ ACE_TRACE ("Server::Server");
+ }
+
+ virtual int init (int argc, ACE_TCHAR *argv[])
+ {
+ ACE_TRACE ("Server::init");
+ const ACE_TCHAR *l_addr = argc > 1 ? argv[1] : ACE_DEFAULT_RENDEZVOUS;
+
+ ACE_UPIPE_Addr local_addr (l_addr);
+
+ if (this->thr_strategy_.open (this->thr_mgr_, THR_DETACHED | THR_NEW_LWP) == -1)
+ return -1;
+ else if (this->open (local_addr, this->reactor_,
+ 0, 0, &this->thr_strategy_) == -1)
+ return -1;
+
+ // Give server a chance to register the STREAM pipe.
+ ACE_OS::sleep (ACE_Time_Value (4));
+ return 0;
+ }
+
+private:
+ ACE_Reactor *reactor_;
+ // Our instance of the reactor.
+
+ ACE_Thread_Manager *thr_mgr_;
+ // Our instance of a thread manager.
+
+ ACE_Thread_Strategy<Server_Service> thr_strategy_;
+ // Our concurrency strategy.
+};
+
+class Client : public ACE_Connector <Client_Service, ACE_UPIPE_CONNECTOR>
+{
+ // = TITLE
+ // Defines the interface for a factory that connects
+ // a Client_Service with a Server.
+public:
+ Client (ACE_Thread_Manager *thr_mgr)
+ : thr_mgr_ (thr_mgr)
+ {
+ ACE_TRACE ("Client::Client");
+ }
+
+ virtual int init (int argc, ACE_TCHAR *argv[])
+ {
+ ACE_TRACE ("Client::init");
+
+ const ACE_TCHAR *r_addr = argc > 1 ? argv[1] : ACE_DEFAULT_RENDEZVOUS;
+
+ ACE_UPIPE_Addr remote_addr (r_addr);
+
+ Client_Service *cs;
+
+ ACE_NEW_RETURN (cs, Client_Service (this->thr_mgr_), -1);
+
+ return this->connect (cs, remote_addr);
+ }
+
+private:
+ ACE_Thread_Manager *thr_mgr_;
+};
+
+int
+ACE_TMAIN (int argc, ACE_TCHAR *argv[])
+{
+ ACE_Service_Config svc_conf;
+ ACE_Thread_Manager thr_mgr;
+
+ Client peer_connector (&thr_mgr);
+ Server peer_acceptor (&thr_mgr, ACE_Reactor::instance ());
+
+ // Establish the connection between Acceptor and Connector.
+
+ if (peer_acceptor.init (argc, argv) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("%p\n"), ACE_TEXT ("init")), -1);
+ else if (peer_connector.init (argc, argv) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("%p\n"), ACE_TEXT ("init")), -1);
+
+ // Wait for threads to exit.
+ thr_mgr.wait ();
+ return 0;
+}
+#else
+int
+main (int, char *[])
+{
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "your platform does not support threads\n"),
+ 1);
+}
+#endif /* ACE_HAS_THREADS */
diff --git a/ACE/examples/Connection/misc/test_upipe.h b/ACE/examples/Connection/misc/test_upipe.h
new file mode 100644
index 00000000000..89349760e9c
--- /dev/null
+++ b/ACE/examples/Connection/misc/test_upipe.h
@@ -0,0 +1,76 @@
+/* -*- C++ -*- */
+
+// $Id$
+
+#ifndef ACE_TEST_UPIPE_H
+#define ACE_TEST_UPIPE_H
+
+#include "ace/OS_NS_unistd.h"
+#include "ace/Svc_Handler.h"
+#include "ace/Service_Config.h"
+#include "ace/UPIPE_Stream.h"
+
+typedef ACE_Svc_Handler <ACE_UPIPE_STREAM, ACE_NULL_SYNCH> SVC_HANDLER;
+
+class Server_Service : public SVC_HANDLER
+ // = TITLE
+ // Defines the interface for a service that recvs data from its
+ // client and writes the data to its stdout.
+{
+public:
+ Server_Service (ACE_Thread_Manager * = 0) {}
+
+ virtual int open (void *)
+ {
+ ACE_TRACE ("Server_Service::open");
+ return 0;
+ }
+
+ virtual int svc (void)
+ {
+ ACE_TRACE ("Server_Service::svc");
+
+ char buf[BUFSIZ];
+ ssize_t n;
+
+ while ((n = this->peer ().recv (buf, sizeof buf)) > 0)
+ ::write (1, buf, n);
+
+ return 0;
+ }
+};
+
+
+class Client_Service : public SVC_HANDLER
+ // = TITLE
+ // Defines the interface for a service that recvs data from its
+ // stdin and forward the data to its server.
+{
+public:
+ Client_Service (ACE_Thread_Manager *thr_mgr = 0)
+ : SVC_HANDLER (thr_mgr)
+ {
+ ACE_TRACE ("Client_Service::Client_Service");
+ }
+
+ virtual int open (void *)
+ {
+ ACE_TRACE ("Client_Service::open");
+ return this->activate (THR_DETACHED | THR_NEW_LWP);
+ }
+
+ virtual int svc (void)
+ {
+ ACE_TRACE ("Client_Service::svc");
+ char buf[BUFSIZ];
+ ssize_t n;
+
+ while ((n = ACE_OS::read (ACE_STDIN, buf, sizeof buf)) > 0)
+ this->peer ().send (buf, n);
+
+ this->peer ().close ();
+ return 0;
+ }
+};
+
+#endif /* ACE_TEST_UPIPE_H */
diff --git a/ACE/examples/Connection/non_blocking/.cvsignore b/ACE/examples/Connection/non_blocking/.cvsignore
new file mode 100644
index 00000000000..0cbd7c83956
--- /dev/null
+++ b/ACE/examples/Connection/non_blocking/.cvsignore
@@ -0,0 +1,16 @@
+lsock_client
+lsock_client
+lsock_server
+lsock_server
+sock_client
+sock_client
+sock_server
+sock_server
+spipe_client
+spipe_client
+spipe_server
+spipe_server
+tli_client
+tli_client
+tli_server
+tli_server
diff --git a/ACE/examples/Connection/non_blocking/CPP-acceptor.cpp b/ACE/examples/Connection/non_blocking/CPP-acceptor.cpp
new file mode 100644
index 00000000000..12c80c1d939
--- /dev/null
+++ b/ACE/examples/Connection/non_blocking/CPP-acceptor.cpp
@@ -0,0 +1,247 @@
+// $Id$
+
+#if !defined (CPP_ACCEPTOR_C)
+
+#define CPP_ACCEPTOR_C
+
+#include "ace/Service_Config.h"
+#include "CPP-acceptor.h"
+#include "ace/OS_NS_unistd.h"
+#include "ace/Signal.h"
+
+ACE_RCSID(non_blocking, CPP_acceptor, "$Id$")
+
+#define PR_ST_1 ACE_PEER_STREAM_1
+#define PR_ST_2 ACE_PEER_STREAM_2
+#define PR_AC_1 ACE_PEER_ACCEPTOR_1
+#define PR_AC_2 ACE_PEER_ACCEPTOR_2
+#define PR_AD ACE_PEER_STREAM_ADDR
+#define SVH SVC_HANDLER
+
+template <PR_ST_1>
+Svc_Handler<PR_ST_2>::Svc_Handler (ACE_Reactor *r)
+ : SVC_HANDLER (0, 0, r)
+{
+}
+
+template <PR_ST_1> int
+Svc_Handler<PR_ST_2>::close (u_long)
+{
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("calling Svc_Handler close\n")));
+
+ // Free up the handle.
+ this->peer ().close ();
+ return 0;
+}
+
+template <PR_ST_1> int
+Svc_Handler<PR_ST_2>::open (void *)
+{
+ PR_AD client_addr;
+ ACE_TCHAR buf[BUFSIZ];
+
+ if (this->peer ().get_remote_addr (client_addr) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("get_remote_addr")),
+ -1);
+ else if (client_addr.addr_to_string (buf,
+ sizeof buf) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("addr_to_string")),
+ -1);
+ else
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("client addr %s on handle %d\n"),
+ buf,
+ this->peer ().get_handle ()));
+
+ // Process the connection immediately since we are an interative
+ // server.
+ return this->handle_input ();
+}
+
+// Receive and process the data from the client.
+
+template <PR_ST_1> int
+Svc_Handler<PR_ST_2>::handle_input (ACE_HANDLE)
+{
+ char buf[BUFSIZ];
+
+ // Read data from client (terminate on error).
+
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("(%t) in handle_input\n")));
+
+ for (ssize_t r_bytes;
+ (r_bytes = this->peer ().recv (buf,
+ sizeof buf)) > 0;
+ )
+ if (ACE_OS::write (ACE_STDOUT,
+ buf,
+ r_bytes) != r_bytes)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("ACE::send_n")),
+ -1);
+ // Send back ack.
+ if (this->peer ().send_n ("",
+ 1) != 1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("send_n")),
+ -1);
+ return 0;
+}
+
+template <PR_ST_1> int
+Svc_Handler<PR_ST_2>::handle_timeout (const ACE_Time_Value &,
+ const void *)
+{
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("%p\n"), ACE_TEXT ("handle_timeout")));
+ return 0;
+}
+
+template <class SVH, PR_AC_1> int
+IPC_Server<SVH, PR_AC_2>::init (int argc, ACE_TCHAR *argv[])
+{
+ const ACE_TCHAR *local_addr = argc > 1
+ ? argv[1]
+ : ACE_DEFAULT_SERVER_PORT_STR;
+ ACE_Time_Value timeout (argc > 2
+ ? ACE_OS::atoi (argv[2])
+ : ACE_DEFAULT_TIMEOUT);
+ int use_reactor = argc > 3
+ ? ACE_Synch_Options::USE_REACTOR
+ : 0;
+
+ this->options_.set (ACE_Synch_Options::USE_TIMEOUT | use_reactor,
+ timeout);
+
+ if (this->server_addr_.set (local_addr) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("set")),
+ -1);
+ // Call down to the ACCEPTOR's <open> method to do the
+ // initialization.
+ if (this->inherited::open (this->server_addr_,
+ use_reactor
+ ? ACE_Reactor::instance ()
+ : 0) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("open")),
+ -1);
+ // Handle the SIGINT signal through the <ACE_Reactor>.
+ else if (ACE_Reactor::instance ()->register_handler
+ (SIGINT,
+ &this->done_handler_) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("register_handler")),
+ -1);
+#if !defined (ACE_WIN32)
+ // Handle the SIGPIPE signal through the <ACE_Reactor>.
+ else if (ACE_Reactor::instance ()->register_handler
+ (SIGPIPE,
+ &this->done_handler_) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("register_handler")),
+ -1);
+#endif /* ACE_WIN32 */
+ else
+ return 0;
+}
+
+template <class SVH, PR_AC_1>
+IPC_Server<SVH, PR_AC_2>::IPC_Server (void)
+ : done_handler_ (ACE_Sig_Handler_Ex (ACE_Reactor::end_event_loop))
+{
+}
+
+template <class SVH, PR_AC_1> int
+IPC_Server<SVH, PR_AC_2>::fini (void)
+{
+ return 0;
+}
+
+template <class SVH, PR_AC_1>
+IPC_Server<SVH, PR_AC_2>::~IPC_Server (void)
+{
+}
+
+template <class SVH, PR_AC_1> int
+IPC_Server<SVH, PR_AC_2>::handle_close (ACE_HANDLE handle,
+ ACE_Reactor_Mask mask)
+{
+ ACE_UNUSED_ARG (handle);
+ ACE_UNUSED_ARG (mask);
+
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("calling IPC_Server handle_close, but accept handle stays open!\n")));
+ return 0;
+}
+
+// Run the interative service.
+
+template <class SVH, PR_AC_1> int
+IPC_Server<SVH, PR_AC_2>::svc (void)
+{
+ ACE_TCHAR buf[BUFSIZ];
+
+ if (this->server_addr_.addr_to_string (buf,
+ sizeof buf) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("addr_to_string")),
+ -1);
+ else
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("starting server addr %s on handle %d\n"),
+ buf,
+ this->get_handle ()));
+
+ // Performs the iterative server activities.
+
+ while (ACE_Reactor::event_loop_done () == 0)
+ {
+ SVH sh (this->reactor ());
+
+ // Create a new <SVH> endpoint, which performs all processing in
+ // its <open> method (note no automatic restart if errno ==
+ // EINTR).
+
+ if (this->accept (&sh,
+ 0,
+ this->options_,
+ 0) == -1)
+ {
+ if (errno == EWOULDBLOCK
+ && this->reactor ())
+ // Handle the accept asynchronously if necessary.
+ this->reactor ()->handle_events ();
+ else
+ // We've probably timed out...
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("%p on handle %d\n"),
+ ACE_TEXT ("accept"),
+ this->acceptor ().get_handle ()));
+ }
+
+ // <SVH>'s destructor closes the stream implicitly but the
+ // listening endpoint stays open.
+ }
+
+ /* NOTREACHED */
+ return 0;
+}
+
+#undef PR_ST_1
+#undef PR_ST_2
+#undef PR_AC_1
+#undef PR_AC_2
+#undef PR_AD
+#undef SVH
+#endif /* CPP_ACCEPTOR_C */
diff --git a/ACE/examples/Connection/non_blocking/CPP-acceptor.h b/ACE/examples/Connection/non_blocking/CPP-acceptor.h
new file mode 100644
index 00000000000..c06caf50b48
--- /dev/null
+++ b/ACE/examples/Connection/non_blocking/CPP-acceptor.h
@@ -0,0 +1,96 @@
+/* -*- C++ -*- */
+// $Id$
+
+#ifndef CPP_ACCEPTOR_H
+#define CPP_ACCEPTOR_H
+
+#include "ace/Acceptor.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/Svc_Handler.h"
+#include "ace/Sig_Adapter.h"
+
+
+template <ACE_PEER_STREAM_1>
+class Svc_Handler : public ACE_Svc_Handler <ACE_PEER_STREAM_2, ACE_NULL_SYNCH>
+{
+ // = TITLE
+ // This class does the work once the <ACE_Oneshot_Acceptor> has
+ // accepted a connection.
+public:
+ // = Initialization method.
+ Svc_Handler (ACE_Reactor *r);
+
+ virtual int open (void *);
+ // Perform the work of the SVC_HANDLER.
+
+ virtual int handle_input (ACE_HANDLE = ACE_INVALID_HANDLE);
+ // Handle data from the client.
+
+ virtual int close (u_long);
+ // Called if ACE_Svc_Handler is closed down unexpectedly.
+
+ virtual int handle_timeout (const ACE_Time_Value &, const void *arg);
+ // Handles acceptor timeouts.
+
+private:
+ typedef ACE_Svc_Handler <ACE_PEER_STREAM_2, ACE_NULL_SYNCH>
+ SVC_HANDLER;
+};
+
+template <class SVC_HANDLER, ACE_PEER_ACCEPTOR_1>
+class IPC_Server : public ACE_Oneshot_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>
+{
+ // = TITLE
+ // This class illustrates how the <ACE_Oneshot_Acceptor> works.
+public:
+ // = Initialization and termination.
+ IPC_Server (void);
+ // Constructor.
+
+ ~IPC_Server (void);
+ // Destructor.
+
+ // = Demultiplexing hooks.
+ virtual int handle_close (ACE_HANDLE handle,
+ ACE_Reactor_Mask mask);
+ // Make sure not to close down the <handle> if we're removed from
+ // the <Reactor>.
+
+ // = Dynamic linking hooks.
+ virtual int init (int argc, ACE_TCHAR *argv[]);
+ // Initialize the network server.
+
+ virtual int fini (void);
+ // Close down the server.
+
+ virtual int svc (void);
+ // Run the interative service.
+
+private:
+ typedef ACE_Oneshot_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>
+ inherited;
+
+ ACE_PEER_ACCEPTOR_ADDR server_addr_;
+ // Address of this server.
+
+ ACE_Synch_Options options_;
+ // Options that this server is using.
+
+ ACE_Sig_Adapter done_handler_;
+ // Keeps track of when we shut down due to receipt of the SIGINT
+ // signal.
+};
+
+#if defined (ACE_TEMPLATES_REQUIRE_SOURCE)
+#include "CPP-acceptor.cpp"
+#endif /* ACE_TEMPLATES_REQUIRE_SOURCE */
+
+#if defined (ACE_TEMPLATES_REQUIRE_PRAGMA)
+#pragma implementation ("CPP-acceptor.cpp")
+#endif /* ACE_TEMPLATES_REQUIRE_PRAGMA */
+
+#endif /* CPP_ACCEPTOR_H */
diff --git a/ACE/examples/Connection/non_blocking/CPP-connector.cpp b/ACE/examples/Connection/non_blocking/CPP-connector.cpp
new file mode 100644
index 00000000000..e113b5f5acb
--- /dev/null
+++ b/ACE/examples/Connection/non_blocking/CPP-connector.cpp
@@ -0,0 +1,289 @@
+// $Id$
+
+#if !defined (CPP_CONNECTOR_C)
+#define CPP_CONNECTOR_C
+
+#include "CPP-connector.h"
+#include "ace/OS_NS_stdio.h"
+#include "ace/OS_NS_unistd.h"
+#include "ace/Signal.h"
+
+ACE_RCSID(non_blocking, CPP_connector, "$Id$")
+
+#define PR_ST_1 ACE_PEER_STREAM_1
+#define PR_ST_2 ACE_PEER_STREAM_2
+#define PR_CO_1 ACE_PEER_CONNECTOR_1
+#define PR_CO_2 ACE_PEER_CONNECTOR_2
+#define PR_AD ACE_PEER_CONNECTOR_ADDR
+#define SVH SVC_HANDLER
+
+template <PR_ST_1>
+Peer_Handler<PR_ST_2>::Peer_Handler (ACE_Reactor *r)
+ : action_ (&Peer_Handler<PR_ST_2>::uninitialized)
+{
+ this->reactor (r);
+}
+
+template <PR_ST_1> int
+Peer_Handler<PR_ST_2>::open (void *)
+{
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("activating %d\n"),
+ this->peer ().get_handle ()));
+ this->action_ = &Peer_Handler<PR_ST_2>::connected;
+
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("please enter input..: ")));
+
+ if (this->reactor ())
+
+#if defined (ACE_WIN32)
+ // On Win32, the stdin HANDLE must be registered directly (and not
+ // as a socket).
+ this->reactor ()->register_handler (this,
+ ACE_STDIN);
+#else
+ // On non-Win32, the stdin HANDLE must be registered as a normal
+ // handle with the <READ_Mask>.
+ this->reactor ()->register_handler (ACE_STDIN,
+ this,
+ ACE_Event_Handler::READ_MASK);
+#endif /* ACE_WIN32 */
+ else
+ {
+ while (this->connected () != -1)
+ continue;
+
+ this->handle_close (ACE_INVALID_HANDLE,
+ ACE_Event_Handler::READ_MASK);
+ }
+ return 0;
+}
+
+template <PR_ST_1> int
+Peer_Handler<PR_ST_2>::close (u_long)
+{
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("Connect not successful: ending reactor event loop\n")));
+ this->reactor ()->end_reactor_event_loop();
+ return 0;
+}
+
+template <PR_ST_1> int
+Peer_Handler<PR_ST_2>::uninitialized (void)
+{
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("uninitialized!\n")));
+ return 0;
+}
+
+template <PR_ST_1> int
+Peer_Handler<PR_ST_2>::connected (void)
+{
+ char buf[BUFSIZ];
+
+ ssize_t n = ACE_OS::read (ACE_STDIN,
+ buf,
+ sizeof buf);
+
+ if (n > 0
+ && this->peer ().send_n (buf,
+ n) != n)
+ ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("%p\n"), ACE_TEXT ("write failed")),
+ -1);
+ else if (n == 0)
+ {
+ // Explicitly close the connection.
+ if (this->peer ().close () == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("close")),
+ 1);
+ return -1;
+ }
+ else
+ {
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("please enter input..: ")));
+ return 0;
+ }
+}
+
+template <PR_ST_1> int
+Peer_Handler<PR_ST_2>::stdio (void)
+{
+ char buf[BUFSIZ];
+
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("in stdio\nplease enter input..: ")));
+
+ ssize_t n = ACE_OS::read (ACE_STDIN,
+ buf,
+ sizeof buf);
+ if (n > 0)
+ {
+ if (ACE_OS::write (ACE_STDOUT,
+ buf,
+ n) != n)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("write")),
+ -1);
+ return 0;
+ }
+ else
+ return -1;
+}
+
+template <PR_ST_1> int
+Peer_Handler<PR_ST_2>::handle_timeout (const ACE_Time_Value &,
+ const void *)
+{
+ ACE_ERROR ((LM_ERROR, ACE_TEXT ("Connect timedout. ")));
+ return this->close ();
+}
+
+template <PR_ST_1> int
+Peer_Handler<PR_ST_2>::handle_output (ACE_HANDLE)
+{
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("in handle_output\n")));
+
+ return (this->*action_) ();
+}
+
+template <PR_ST_1> int
+Peer_Handler<PR_ST_2>::handle_signal (int signum,
+ siginfo_t *,
+ ucontext_t *)
+{
+ ACE_UNUSED_ARG (signum);
+
+ // @@ Note that this code is not portable to all OS platforms since
+ // it uses print statements within signal handler context.
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("in handle_signal\n")));
+
+ return (this->*action_) ();
+}
+
+template <PR_ST_1> int
+Peer_Handler<PR_ST_2>::handle_input (ACE_HANDLE)
+{
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("in handle_input\n")));
+
+ return (this->*action_) ();
+}
+
+template <PR_ST_1> int
+Peer_Handler<PR_ST_2>::handle_close (ACE_HANDLE h,
+ ACE_Reactor_Mask mask)
+{
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("closing down handle %d with mask %d\n"),
+ h,
+ mask));
+
+ if (this->action_ == &Peer_Handler<PR_ST_2>::stdio)
+ {
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("moving to closed state\n")));
+ this->reactor ()->end_reactor_event_loop ();
+ }
+ else
+ {
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("moving to stdio state\n")));
+ this->action_ = &Peer_Handler<PR_ST_2>::stdio;
+ this->peer ().close ();
+ ACE_OS::rewind (stdin);
+
+ if (this->reactor ())
+#if defined (ACE_WIN32)
+ // On Win32, the std handle must be registered directly (and not
+ // as a socket)
+ return this->reactor ()->register_handler (this,
+ ACE_STDIN);
+#else
+ // On non-Win32, the std handle must be registered as a normal
+ // handle with the READ mask
+ return this->reactor ()->register_handler (ACE_STDIN,
+ this,
+ ACE_Event_Handler::READ_MASK);
+#endif /* ACE_WIN32 */
+ else
+ delete this;
+ }
+
+ return 0;
+}
+
+template <class SVH, PR_CO_1> int
+IPC_Client<SVH, PR_CO_2>::svc (void)
+{
+ if (this->reactor ())
+ this->reactor ()->run_reactor_event_loop ();
+
+ return 0;
+}
+
+template <class SVH, PR_CO_1> int
+IPC_Client<SVH, PR_CO_2>::fini (void)
+{
+ return 0;
+}
+
+template <class SVH, PR_CO_1>
+IPC_Client<SVH, PR_CO_2>::IPC_Client (void)
+ : done_handler_ (ACE_Sig_Handler_Ex (ACE_Reactor::end_event_loop))
+{
+}
+
+template <class SVH, PR_CO_1> int
+IPC_Client<SVH, PR_CO_2>::init (int argc, ACE_TCHAR *argv[])
+{
+ // Call down to the CONNECTOR's open() method to do the
+ // initialization.
+ this->inherited::open (ACE_Reactor::instance ());
+
+ const ACE_TCHAR *r_addr = argc > 1 ? argv[1] :
+ ACE_SERVER_ADDRESS (ACE_DEFAULT_SERVER_HOST,
+ ACE_DEFAULT_SERVER_PORT_STR);
+ ACE_Time_Value timeout (argc > 2
+ ? ACE_OS::atoi (argv[2])
+ : ACE_DEFAULT_TIMEOUT);
+
+ // Handle signals through the ACE_Reactor.
+ if (ACE_Reactor::instance ()->register_handler
+ (SIGINT,
+ &this->done_handler_) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("register_handler")),
+ -1);
+ PR_AD remote_addr (r_addr);
+ this->options_.set (ACE_Synch_Options::USE_REACTOR,
+ timeout);
+
+ SVH *sh;
+ ACE_NEW_RETURN (sh,
+ SVH (this->reactor ()),
+ -1);
+
+ // Connect to the peer.
+ if (this->connect (sh,
+ remote_addr,
+ this->options_) == -1
+ && errno != EWOULDBLOCK)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("connect")),
+ -1);
+ else
+ return 0;
+}
+
+template <class SVH, PR_CO_1>
+IPC_Client<SVH, PR_CO_2>::~IPC_Client (void)
+{
+}
+
+#undef PR_ST_1
+#undef PR_ST_2
+#undef PR_CO_1
+#undef PR_CO_2
+#undef PR_AD
+#undef SVH
+#endif /* CPP_CONNECTOR_C */
diff --git a/ACE/examples/Connection/non_blocking/CPP-connector.h b/ACE/examples/Connection/non_blocking/CPP-connector.h
new file mode 100644
index 00000000000..86ce63493f0
--- /dev/null
+++ b/ACE/examples/Connection/non_blocking/CPP-connector.h
@@ -0,0 +1,98 @@
+/* -*- C++ -*- */
+// $Id$
+
+#ifndef CPP_CONNECTOR_H
+#define CPP_CONNECTOR_H
+
+#include "ace/Service_Config.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/Connector.h"
+#include "ace/Svc_Handler.h"
+#include "ace/Sig_Adapter.h"
+
+template <ACE_PEER_STREAM_1>
+class Peer_Handler : public ACE_Svc_Handler<ACE_PEER_STREAM_2, ACE_SYNCH>
+{
+ // = TITLE
+ // Handles communication with the server.
+ //
+ // = DESCRIPTION
+ // This class uses a very clever state machine pattern to keep
+ // track of how it interacts with the user and the server.
+public:
+ Peer_Handler (ACE_Reactor *r = 0);
+
+ virtual int open (void * = 0);
+ // Activate the handler when connection is established.
+
+ virtual int close (u_long flags = 0);
+ // Called on failed connection attempt.
+
+ // = Demultiplexing hooks.
+ virtual int handle_output (ACE_HANDLE);
+ virtual int handle_input (ACE_HANDLE);
+ virtual int handle_close (ACE_HANDLE,
+ ACE_Reactor_Mask mask);
+ virtual int handle_signal (int signum,
+ siginfo_t * = 0,
+ ucontext_t * = 0);
+ virtual int handle_timeout (const ACE_Time_Value &time,
+ const void *);
+protected:
+ // = These methods implement the State pattern.
+ int uninitialized (void);
+ int connected (void);
+ int stdio (void);
+
+ int (Peer_Handler<ACE_PEER_STREAM_2>::*action_) (void);
+ // Keeps track of which state we are in.
+};
+
+template <class SVC_HANDLER, ACE_PEER_CONNECTOR_1>
+class IPC_Client : public ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>
+{
+ // = TITLE
+ // This class illustrates how the <ACE_Connector> works.
+public:
+ // = Initialization and termination methods.
+ IPC_Client (void);
+ // Constructor.
+
+ ~IPC_Client (void);
+ // Destructor.
+
+ // = Dynamic linking hooks.
+ virtual int init (int argc, ACE_TCHAR *argv[]);
+ // Initialize the IPC client.
+
+ virtual int fini (void);
+ // Destroy the IPC client.
+
+ virtual int svc (void);
+ // Run the svc.
+
+private:
+ typedef ACE_Connector<SVC_HANDLER, ACE_PEER_CONNECTOR_2>
+ inherited;
+
+ ACE_Synch_Options options_;
+ // Options for the active connection factory.
+
+ ACE_Sig_Adapter done_handler_;
+ // Keeps track of when we shut down due to receipt of the SIGINT
+ // signal.
+};
+
+#if defined (ACE_TEMPLATES_REQUIRE_SOURCE)
+#include "CPP-connector.cpp"
+#endif /* ACE_TEMPLATES_REQUIRE_SOURCE */
+
+#if defined (ACE_TEMPLATES_REQUIRE_PRAGMA)
+#pragma implementation ("CPP-connector.cpp")
+#endif /* ACE_TEMPLATES_REQUIRE_PRAGMA */
+
+#endif /* CPP_CONNECTOR_H */
diff --git a/ACE/examples/Connection/non_blocking/Connection_Non_Blocking.mpc b/ACE/examples/Connection/non_blocking/Connection_Non_Blocking.mpc
new file mode 100644
index 00000000000..de9ecaea5e0
--- /dev/null
+++ b/ACE/examples/Connection/non_blocking/Connection_Non_Blocking.mpc
@@ -0,0 +1,68 @@
+// -*- MPC -*-
+// $Id$
+
+project (*SockClient) : aceexe {
+ exename = sock_client
+ Source_Files {
+ CPP-connector.cpp
+ test_sock_connector.cpp
+ }
+}
+
+project (*SockServer) : aceexe {
+ exename = sock_server
+ Source_Files {
+ CPP-acceptor.cpp
+ test_sock_acceptor.cpp
+ }
+}
+
+project (*LSockClient) : aceexe {
+ avoids += ace_for_tao
+ exename = lsock_client
+ Source_Files {
+ CPP-connector.cpp
+ test_lsock_connector.cpp
+ }
+}
+
+project (*LSockServer) : aceexe {
+ avoids += ace_for_tao
+ exename = lsock_server
+ Source_Files {
+ CPP-acceptor.cpp
+ test_lsock_acceptor.cpp
+ }
+}
+
+project (*SPipeClient) : aceexe {
+ exename = spipe_client
+ Source_Files {
+ CPP-connector.cpp
+ test_spipe_connector.cpp
+ }
+}
+
+project (*SPipeServer) : aceexe {
+ exename = spipe_server
+ Source_Files {
+ CPP-acceptor.cpp
+ test_spipe_acceptor.cpp
+ }
+}
+
+project (*TLIClient) : aceexe {
+ exename = tli_client
+ Source_Files {
+ CPP-connector.cpp
+ test_tli_connector.cpp
+ }
+}
+
+project (*TLIServer) : aceexe {
+ exename = tli_server
+ Source_Files {
+ CPP-acceptor.cpp
+ test_tli_acceptor.cpp
+ }
+}
diff --git a/ACE/examples/Connection/non_blocking/Makefile.am b/ACE/examples/Connection/non_blocking/Makefile.am
new file mode 100644
index 00000000000..8395e3a9fbb
--- /dev/null
+++ b/ACE/examples/Connection/non_blocking/Makefile.am
@@ -0,0 +1,150 @@
+## Process this file with automake to create Makefile.in
+##
+## $Id$
+##
+## This file was generated by MPC. Any changes made directly to
+## this file will be lost the next time it is generated.
+##
+## MPC Command:
+## /acebuilds/ACE_wrappers-repository/bin/mwc.pl -include /acebuilds/MPC/config -include /acebuilds/MPC/templates -feature_file /acebuilds/ACE_wrappers-repository/local.features -noreldefs -type automake -exclude build,Kokyu
+
+ACE_BUILDDIR = $(top_builddir)
+ACE_ROOT = $(top_srcdir)
+
+noinst_PROGRAMS =
+
+## Makefile.Connection_Non_Blocking_LSockClient.am
+
+if !BUILD_ACE_FOR_TAO
+noinst_PROGRAMS += lsock_client
+
+lsock_client_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+lsock_client_SOURCES = \
+ CPP-connector.cpp \
+ test_lsock_connector.cpp \
+ CPP-connector.h
+
+lsock_client_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+endif !BUILD_ACE_FOR_TAO
+
+## Makefile.Connection_Non_Blocking_LSockServer.am
+
+if !BUILD_ACE_FOR_TAO
+noinst_PROGRAMS += lsock_server
+
+lsock_server_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+lsock_server_SOURCES = \
+ CPP-acceptor.cpp \
+ test_lsock_acceptor.cpp \
+ CPP-acceptor.h
+
+lsock_server_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+endif !BUILD_ACE_FOR_TAO
+
+## Makefile.Connection_Non_Blocking_SPipeClient.am
+noinst_PROGRAMS += spipe_client
+
+spipe_client_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+spipe_client_SOURCES = \
+ CPP-connector.cpp \
+ test_spipe_connector.cpp \
+ CPP-connector.h
+
+spipe_client_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Makefile.Connection_Non_Blocking_SPipeServer.am
+noinst_PROGRAMS += spipe_server
+
+spipe_server_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+spipe_server_SOURCES = \
+ CPP-acceptor.cpp \
+ test_spipe_acceptor.cpp \
+ CPP-acceptor.h
+
+spipe_server_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Makefile.Connection_Non_Blocking_SockClient.am
+noinst_PROGRAMS += sock_client
+
+sock_client_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+sock_client_SOURCES = \
+ CPP-connector.cpp \
+ test_sock_connector.cpp \
+ CPP-connector.h
+
+sock_client_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Makefile.Connection_Non_Blocking_SockServer.am
+noinst_PROGRAMS += sock_server
+
+sock_server_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+sock_server_SOURCES = \
+ CPP-acceptor.cpp \
+ test_sock_acceptor.cpp \
+ CPP-acceptor.h
+
+sock_server_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Makefile.Connection_Non_Blocking_TLIClient.am
+noinst_PROGRAMS += tli_client
+
+tli_client_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+tli_client_SOURCES = \
+ CPP-connector.cpp \
+ test_tli_connector.cpp \
+ CPP-connector.h
+
+tli_client_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Makefile.Connection_Non_Blocking_TLIServer.am
+noinst_PROGRAMS += tli_server
+
+tli_server_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+tli_server_SOURCES = \
+ CPP-acceptor.cpp \
+ test_tli_acceptor.cpp \
+ CPP-acceptor.h
+
+tli_server_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Clean up template repositories, etc.
+clean-local:
+ -rm -f *~ *.bak *.rpo *.sym lib*.*_pure_* core core.*
+ -rm -f gcctemp.c gcctemp so_locations *.ics
+ -rm -rf cxx_repository ptrepository ti_files
+ -rm -rf templateregistry ir.out
+ -rm -rf ptrepository SunWS_cache Templates.DB
diff --git a/ACE/examples/Connection/non_blocking/README b/ACE/examples/Connection/non_blocking/README
new file mode 100644
index 00000000000..74c44fe6de7
--- /dev/null
+++ b/ACE/examples/Connection/non_blocking/README
@@ -0,0 +1,28 @@
+This code illustrates how to write a single set of source code (for a
+client and server) and then parameterize in the desired IPC mechanism.
+In this case, the IPC mechanisms include sockets, TLI, and STREAM
+pipes. The single set of source code is located in CPP-acceptor.cpp
+(which is the server) and CPP-connector.cpp (which is the non-blocking
+client).
+
+Here's how I typically run these tests:
+
+% test_sock_acceptor localhost:10020 &
+starting up daemon ./test_sock_acceptor
+starting server addr 127.0.0.1:10020 on handle 5
+client addr 127.0.0.1:10003 on handle 6
+hello
+
+% test_sock_connector localhost:10020
+starting up daemon ./test_sock_connector
+activating 5
+in handle_output
+please enter input..: hello
+in handle_output
+
+There are a number of other options that you can provide. Please see
+the source code for details.
+
+Note that only the sock tests work on all platforms. The other tests
+reply on features (in particular, non-blocking connections and TLI)
+that are mostly found on UNIX platforms.
diff --git a/ACE/examples/Connection/non_blocking/test_lsock_acceptor.cpp b/ACE/examples/Connection/non_blocking/test_lsock_acceptor.cpp
new file mode 100644
index 00000000000..cdfcfe5e65c
--- /dev/null
+++ b/ACE/examples/Connection/non_blocking/test_lsock_acceptor.cpp
@@ -0,0 +1,49 @@
+// $Id$
+
+// ACE_LSOCK Server.
+
+#include "ace/LSOCK_Acceptor.h"
+#include "ace/Log_Msg.h"
+#include "ace/Service_Config.h"
+
+
+#if defined (ACE_LACKS_UNIX_DOMAIN_SOCKETS)
+int
+ACE_TMAIN (int, ACE_TCHAR *argv[])
+{
+ ACE_ERROR_RETURN ((LM_INFO,
+ ACE_TEXT ("%s: not supported with ")
+ ACE_TEXT ("ACE_LACKS_UNIX_DOMAIN_SOCKETS\n"),
+ argv[0]),
+ -1);
+}
+
+#else /* ! ACE_LACKS_UNIX_DOMAIN_SOCKETS */
+
+#include "ace/UNIX_Addr.h"
+#include "CPP-acceptor.h"
+
+ACE_RCSID (non_blocking,
+ test_lsock_acceptor,
+ "$Id$")
+
+typedef Svc_Handler<ACE_LSOCK_STREAM> SVC_HANDLER;
+typedef IPC_Server<SVC_HANDLER, ACE_LSOCK_ACCEPTOR> IPC_SERVER;
+
+int
+ACE_TMAIN (int argc, ACE_TCHAR *argv[])
+{
+ // Perform Service_Config initializations
+ ACE_Service_Config daemon (argv[0]);
+
+ IPC_SERVER peer_acceptor;
+
+ if (peer_acceptor.init (argc, argv) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("init")),
+ -1);
+ return peer_acceptor.svc ();
+}
+
+#endif /* ! ACE_LACKS_UNIX_DOMAIN_SOCKETS */
diff --git a/ACE/examples/Connection/non_blocking/test_lsock_connector.cpp b/ACE/examples/Connection/non_blocking/test_lsock_connector.cpp
new file mode 100644
index 00000000000..486fda797e8
--- /dev/null
+++ b/ACE/examples/Connection/non_blocking/test_lsock_connector.cpp
@@ -0,0 +1,46 @@
+// $Id$
+
+#include "ace/LSOCK_Connector.h"
+#include "ace/Log_Msg.h"
+
+#if defined (ACE_LACKS_UNIX_DOMAIN_SOCKETS)
+int
+ACE_TMAIN (int, ACE_TCHAR *argv[])
+{
+ ACE_ERROR_RETURN ((LM_INFO,
+ ACE_TEXT ("%s: not supported with ")
+ ACE_TEXT ("ACE_LACKS_UNIX_DOMAIN_SOCKETS\n"),
+ argv[0]),
+ -1);
+}
+
+#else /* ! ACE_LACKS_UNIX_DOMAIN_SOCKETS */
+
+#include "ace/UNIX_Addr.h"
+#include "CPP-connector.h"
+
+ACE_RCSID(non_blocking, test_lsock_connector, "$Id$")
+
+typedef Peer_Handler<ACE_LSOCK_STREAM> PEER_HANDLER;
+typedef IPC_Client<PEER_HANDLER, ACE_LSOCK_CONNECTOR> IPC_CLIENT;
+
+// ACE_LSOCK Client.
+
+int
+ACE_TMAIN (int argc, ACE_TCHAR *argv[])
+{
+ // Perform Service_Config initializations
+ ACE_Service_Config daemon (argv[0]);
+
+ IPC_CLIENT peer_connector;
+
+ if (peer_connector.init (argc, argv) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("init")),
+ -1);
+
+ return peer_connector.svc ();
+}
+
+#endif /* ! ACE_LACKS_UNIX_DOMAIN_SOCKETS */
diff --git a/ACE/examples/Connection/non_blocking/test_sock_acceptor.cpp b/ACE/examples/Connection/non_blocking/test_sock_acceptor.cpp
new file mode 100644
index 00000000000..6a9b9fcdcbb
--- /dev/null
+++ b/ACE/examples/Connection/non_blocking/test_sock_acceptor.cpp
@@ -0,0 +1,34 @@
+// $Id$
+
+#include "ace/SOCK_Acceptor.h"
+#include "ace/INET_Addr.h"
+#include "ace/Service_Config.h"
+
+#include "CPP-acceptor.h"
+
+
+ACE_RCSID (non_blocking,
+ test_sock_acceptor,
+ "$Id$")
+
+
+typedef Svc_Handler<ACE_SOCK_STREAM> SVC_HANDLER;
+typedef IPC_Server<SVC_HANDLER, ACE_SOCK_ACCEPTOR> IPC_SERVER;
+
+int
+ACE_TMAIN (int argc, ACE_TCHAR *argv[])
+{
+ // Perform Service_Config initializations
+ ACE_Service_Config daemon (argv[0]);
+
+ IPC_SERVER peer_acceptor;
+
+ if (peer_acceptor.init (argc, argv) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("init")),
+ -1);
+
+ return peer_acceptor.svc ();
+}
+
diff --git a/ACE/examples/Connection/non_blocking/test_sock_connector.cpp b/ACE/examples/Connection/non_blocking/test_sock_connector.cpp
new file mode 100644
index 00000000000..66d53e1f0b2
--- /dev/null
+++ b/ACE/examples/Connection/non_blocking/test_sock_connector.cpp
@@ -0,0 +1,49 @@
+// $Id$
+
+#include "ace/SOCK_Connector.h"
+#include "ace/INET_Addr.h"
+#include "ace/Reactor.h"
+#include "ace/WFMO_Reactor.h"
+#include "CPP-connector.h"
+
+ACE_RCSID(non_blocking, test_sock_connector, "$Id$")
+
+typedef Peer_Handler<ACE_SOCK_STREAM> PEER_HANDLER;
+typedef IPC_Client<PEER_HANDLER, ACE_SOCK_CONNECTOR> IPC_CLIENT;
+
+// ACE_SOCK Client.
+
+int
+ACE_TMAIN (int argc, ACE_TCHAR *argv[])
+{
+ // Since this test waits on the STDIN handle to become ready, we
+ // have to make sure that the WFMO_Reactor is used on Win32. This is
+ // necessary since <select> on NT does not support waiting on STDIN.
+
+#if defined (ACE_WIN32)
+# if defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0)
+ ACE_WFMO_Reactor wfmo_reactor;
+ ACE_Reactor reactor (&wfmo_reactor);
+ ACE_Reactor::instance (&reactor);
+# else
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("Non-NT platform (Win95/98?) without Winsock2 ")
+ ACE_TEXT ("installed.\n")
+ ACE_TEXT ("This example requires WFMO_Reactor which ")
+ ACE_TEXT ("requires.\n")
+ ACE_TEXT ("Winsock2 be installed.\n")), -1);
+# endif /* !ACE_HAS_WINSOCK2 && ACE_HAS_WINSOCK2 != 0 */
+#endif /* ACE_WIN32 */
+
+ // Perform Service_Config initializations
+ ACE_Service_Config daemon (argv[0]);
+
+ IPC_CLIENT peer_connector;
+
+ if (peer_connector.init (argc, argv) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("%p\n"), ACE_TEXT ("init")),
+ -1);
+
+ return peer_connector.svc ();
+}
+
diff --git a/ACE/examples/Connection/non_blocking/test_spipe_acceptor.cpp b/ACE/examples/Connection/non_blocking/test_spipe_acceptor.cpp
new file mode 100644
index 00000000000..ed33bb31683
--- /dev/null
+++ b/ACE/examples/Connection/non_blocking/test_spipe_acceptor.cpp
@@ -0,0 +1,45 @@
+// $Id$
+
+#include "ace/SPIPE_Acceptor.h"
+#include "ace/SPIPE_Addr.h"
+#include "ace/Service_Config.h"
+
+#include "CPP-acceptor.h"
+
+
+ACE_RCSID (non_blocking,
+ test_spipe_acceptor,
+ "$Id$")
+
+
+#if !defined (ACE_WIN32)
+typedef Svc_Handler<ACE_SPIPE_STREAM> SVC_HANDLER;
+typedef IPC_Server<SVC_HANDLER, ACE_SPIPE_ACCEPTOR> IPC_SERVER;
+
+int
+ACE_TMAIN (int argc, ACE_TCHAR *argv[])
+{
+ // Perform Service_Config initializations
+ ACE_Service_Config daemon (argv[0]);
+
+ IPC_SERVER peer_acceptor;
+
+ if (peer_acceptor.init (argc,
+ argv) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("init")),
+ -1);
+
+ return peer_acceptor.svc ();
+}
+
+#else
+int
+ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "This test is not ported to Win32 (yet)\n"),
+ -1);
+}
+#endif /* !ACE_WIN32 */
diff --git a/ACE/examples/Connection/non_blocking/test_spipe_connector.cpp b/ACE/examples/Connection/non_blocking/test_spipe_connector.cpp
new file mode 100644
index 00000000000..fd5641f482d
--- /dev/null
+++ b/ACE/examples/Connection/non_blocking/test_spipe_connector.cpp
@@ -0,0 +1,40 @@
+// $Id$
+
+// ACE_SPIPE Client.
+
+#include "ace/SPIPE_Connector.h"
+#include "ace/SPIPE_Addr.h"
+#include "CPP-connector.h"
+
+ACE_RCSID(non_blocking, test_spipe_connector, "$Id$")
+
+#if !defined (ACE_WIN32)
+typedef Peer_Handler<ACE_SPIPE_STREAM> PEER_HANDLER;
+typedef IPC_Client<PEER_HANDLER, ACE_SPIPE_CONNECTOR> IPC_CLIENT;
+
+int
+ACE_TMAIN (int argc, ACE_TCHAR *argv[])
+{
+ // Perform Service_Config initializations
+ ACE_Service_Config daemon (argv[0]);
+
+ IPC_CLIENT peer_connector;
+
+ if (peer_connector.init (argc, argv) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("init")),
+ -1);
+
+ return peer_connector.svc ();
+}
+
+#else
+int
+ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "This test is not ported to Win32 (yet)\n"),
+ -1);
+}
+#endif /* !ACE_WIN32 */
diff --git a/ACE/examples/Connection/non_blocking/test_tli_acceptor.cpp b/ACE/examples/Connection/non_blocking/test_tli_acceptor.cpp
new file mode 100644
index 00000000000..04cfb488cbb
--- /dev/null
+++ b/ACE/examples/Connection/non_blocking/test_tli_acceptor.cpp
@@ -0,0 +1,41 @@
+// $Id$
+
+// ACE_TLI Server.
+
+#include "ace/TLI_Acceptor.h"
+#include "ace/INET_Addr.h"
+#include "ace/Service_Config.h"
+#include "CPP-acceptor.h"
+
+ACE_RCSID (non_blocking,
+ test_tli_acceptor,
+ "$Id$")
+
+#if defined (ACE_HAS_TLI)
+typedef Svc_Handler<ACE_TLI_STREAM> SVC_HANDLER;
+typedef IPC_Server<SVC_HANDLER, ACE_TLI_ACCEPTOR> IPC_SERVER;
+
+int ACE_TMAIN (int argc, ACE_TCHAR *argv[])
+{
+ // Perform Service_Config initializations
+ ACE_Service_Config daemon (argv[0]);
+
+ IPC_SERVER peer_acceptor;
+
+ if (peer_acceptor.init (argc, argv) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("init")),
+ -1);
+ return peer_acceptor.svc ();
+}
+
+#else
+int
+ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("your platform does not support TLI\n")),
+ 1);
+}
+#endif /* ACE_HAS_TLI */
diff --git a/ACE/examples/Connection/non_blocking/test_tli_connector.cpp b/ACE/examples/Connection/non_blocking/test_tli_connector.cpp
new file mode 100644
index 00000000000..0f1a2bd6064
--- /dev/null
+++ b/ACE/examples/Connection/non_blocking/test_tli_connector.cpp
@@ -0,0 +1,39 @@
+// $Id$
+
+// ACE_TLI Client.
+
+#include "ace/TLI_Connector.h"
+#include "ace/INET_Addr.h"
+#include "CPP-connector.h"
+
+ACE_RCSID(non_blocking, test_tli_connector, "$Id$")
+
+#if defined (ACE_HAS_TLI)
+
+typedef Peer_Handler<ACE_TLI_STREAM> PEER_HANDLER;
+typedef IPC_Client<PEER_HANDLER, ACE_TLI_CONNECTOR> IPC_CLIENT;
+
+int ACE_TMAIN (int argc, ACE_TCHAR *argv[])
+{
+ // Perform Service_Config initializations
+ ACE_Service_Config daemon (argv[0]);
+
+ IPC_CLIENT peer_connector;
+
+ if (peer_connector.init (argc, argv) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("init")),
+ -1);
+ return peer_connector.svc ();
+}
+
+#else
+int
+ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("your platform does not support TLI\n")),
+ 1);
+}
+#endif /* ACE_HAS_TLI */
diff --git a/ACE/examples/DLL/.cvsignore b/ACE/examples/DLL/.cvsignore
new file mode 100644
index 00000000000..c2d3a626997
--- /dev/null
+++ b/ACE/examples/DLL/.cvsignore
@@ -0,0 +1,2 @@
+test_dll
+test_dll
diff --git a/ACE/examples/DLL/DLL.mpc b/ACE/examples/DLL/DLL.mpc
new file mode 100644
index 00000000000..ca8d0a63009
--- /dev/null
+++ b/ACE/examples/DLL/DLL.mpc
@@ -0,0 +1,22 @@
+// -*- MPC -*-
+// $Id$
+
+project(*Newsweek) : acelib {
+ Source_Files {
+ Newsweek.cpp
+ }
+}
+
+project(*Today) : acelib {
+ Source_Files {
+ Today.cpp
+ }
+}
+
+project(*Main) : aceexe {
+ exename = test_dll
+ after += DLL_Newsweek DLL_Today
+ Source_Files {
+ test_dll.cpp
+ }
+}
diff --git a/ACE/examples/DLL/Magazine.h b/ACE/examples/DLL/Magazine.h
new file mode 100644
index 00000000000..6555974494f
--- /dev/null
+++ b/ACE/examples/DLL/Magazine.h
@@ -0,0 +1,42 @@
+/* -*- C++ -*- */
+// $Id$
+
+// ===========================================================
+//
+//
+// = LIBRARY
+// ACE_wrappers/examples/DLL
+//
+// = FILENAME
+// Magazine.h
+//
+// = DESCRIPTION
+// Abstract class whose methods are implemented by the derived
+// classes.
+//
+// = AUTHOR
+// Kirthika Parameswaran <kirthika@cs.wustl.edu>
+//
+// ===========================================================
+
+#ifndef MAGAZINE_H
+#define MAGAZINE_H
+
+class Magazine
+{
+ // = TITLE
+ // This is an abstract class used in the DLL example.
+ //
+ // = DESCRIPTION
+ // This class simply is an inetrface which the derived classes
+ // will exploit.
+public:
+
+ virtual ~Magazine (void) {};
+ // No-op virtual destructor.
+
+ virtual void title (void) = 0;
+ // This method gives the title of the magazine.
+};
+
+#endif /* MAGAZINE_H */
diff --git a/ACE/examples/DLL/Makefile.am b/ACE/examples/DLL/Makefile.am
new file mode 100644
index 00000000000..4973af35bf9
--- /dev/null
+++ b/ACE/examples/DLL/Makefile.am
@@ -0,0 +1,64 @@
+## Process this file with automake to create Makefile.in
+##
+## $Id$
+##
+## This file was generated by MPC. Any changes made directly to
+## this file will be lost the next time it is generated.
+##
+## MPC Command:
+## /acebuilds/ACE_wrappers-repository/bin/mwc.pl -include /acebuilds/MPC/config -include /acebuilds/MPC/templates -feature_file /acebuilds/ACE_wrappers-repository/local.features -noreldefs -type automake -exclude build,Kokyu
+
+ACE_BUILDDIR = $(top_builddir)
+ACE_ROOT = $(top_srcdir)
+
+## Makefile.DLL_Today.am
+
+noinst_LTLIBRARIES = libDLL_Today.la
+
+libDLL_Today_la_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+libDLL_Today_la_SOURCES = \
+ Today.cpp
+
+noinst_HEADERS = \
+ Today.h
+
+## Makefile.DLL_Newsweek.am
+
+noinst_LTLIBRARIES += libDLL_Newsweek.la
+
+libDLL_Newsweek_la_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+libDLL_Newsweek_la_SOURCES = \
+ Newsweek.cpp
+
+noinst_HEADERS += \
+ Newsweek.h
+
+## Makefile.DLL_Main.am
+noinst_PROGRAMS = test_dll
+
+test_dll_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+test_dll_SOURCES = \
+ test_dll.cpp \
+ Magazine.h \
+ Newsweek.h \
+ Today.h
+
+test_dll_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Clean up template repositories, etc.
+clean-local:
+ -rm -f *~ *.bak *.rpo *.sym lib*.*_pure_* core core.*
+ -rm -f gcctemp.c gcctemp so_locations *.ics
+ -rm -rf cxx_repository ptrepository ti_files
+ -rm -rf templateregistry ir.out
+ -rm -rf ptrepository SunWS_cache Templates.DB
diff --git a/ACE/examples/DLL/Newsweek.cpp b/ACE/examples/DLL/Newsweek.cpp
new file mode 100644
index 00000000000..5a48690b350
--- /dev/null
+++ b/ACE/examples/DLL/Newsweek.cpp
@@ -0,0 +1,55 @@
+// $Id$
+
+#define ACE_BUILD_SVC_DLL
+
+#include "Newsweek.h"
+#include "ace/Log_Msg.h"
+#include "ace/svc_export.h"
+#include "ace/OS_Memory.h"
+
+// Implementation of the abstract class method which describes
+// the magazine.
+
+void Newsweek::title (void)
+{
+ ACE_DEBUG ((LM_DEBUG,
+ "Newsweek: Vol. 44923 Stardate: 12.3054\n"));
+}
+
+void *
+Newsweek::operator new (size_t bytes)
+{
+ return ::new char[bytes];
+}
+#if defined (ACE_HAS_NEW_NOTHROW)
+void *
+Newsweek::operator new (size_t bytes, const ACE_nothrow_t&)
+{
+ return ::new (ACE_nothrow) char[bytes];
+}
+#if !defined (ACE_LACKS_PLACEMENT_OPERATOR_DELETE)
+void
+Newsweek::operator delete (void *p, const ACE_nothrow_t&) throw ()
+{
+ delete [] static_cast <char *> (p);
+}
+#endif /* ACE_LACKS_PLACEMENT_OPERATOR_DELETE */
+#endif
+void
+Newsweek::operator delete (void *ptr)
+{
+ delete [] static_cast <char *> (ptr);
+}
+
+// Returns the Newsweek class pointer.
+// The ACE_BUILD_SVC_DLL and ACE_Svc_Export directives are necessary to
+// take care of exporting the function for Win32 platforms.
+extern "C" ACE_Svc_Export Magazine *create_magazine (void);
+
+Magazine *
+create_magazine (void)
+{
+ Magazine *mag = 0;
+ ACE_NEW_RETURN (mag, Newsweek, 0);
+ return mag;
+}
diff --git a/ACE/examples/DLL/Newsweek.h b/ACE/examples/DLL/Newsweek.h
new file mode 100644
index 00000000000..79355e74cbd
--- /dev/null
+++ b/ACE/examples/DLL/Newsweek.h
@@ -0,0 +1,59 @@
+/* -*- C++ -*- */
+// $Id$
+
+// ===========================================================
+//
+// = LIBRARY
+// ACE_wrappers/examples/DLL
+//
+// = FILENAME
+// Newsweek.h
+//
+// = DESCRIPTION
+// This is a derived class from Magazine which is a magazine
+// pertaining to news and information.
+//
+// = AUTHOR
+// Kirthika Parameswaran <kirthika@cs.wustl.edu>
+//
+// ===========================================================
+
+#ifndef NEWSWEEK_H
+#define NEWSWEEK_H
+
+#include "ace/os_include/os_stddef.h"
+#include "ace/OS_Memory.h"
+#include "Magazine.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+class Newsweek : public Magazine
+{
+ //= TITLE
+ // This is an derived class of Magazine.
+ //
+ //= DESCRIPTION
+ // Polymoriphism is exploited and an object pointer
+ // of Magazine is bound to the Newsweek object at runtime.
+public:
+
+ // This is the abstract class method which describes the magazine.
+ void title (void);
+
+ // Overload the new/delete opertors so the object will be
+ // created/deleted using the memory allocator associated with the
+ // DLL/SO.
+ void *operator new (size_t bytes);
+#if defined (ACE_HAS_NEW_NOTHROW)
+ // Overloaded new operator, nothrow_t variant.
+ void *operator new (size_t bytes, const ACE_nothrow_t&);
+#if !defined (ACE_LACKS_PLACEMENT_OPERATOR_DELETE)
+ void operator delete (void *p, const ACE_nothrow_t&) throw ();
+#endif /* ACE_LACKS_PLACEMENT_OPERATOR_DELETE */
+#endif
+ void operator delete (void *ptr);
+};
+
+# endif /* NEWSWEEK_H */
diff --git a/ACE/examples/DLL/README b/ACE/examples/DLL/README
new file mode 100644
index 00000000000..716b2c2b628
--- /dev/null
+++ b/ACE/examples/DLL/README
@@ -0,0 +1,47 @@
+$Id$
+
+DLL Test Example
+----------------
+
+This example deals with dynamically opening objects and accessing
+methods from it.
+
+First, the pointer to the object is obtained by accessing symbol
+of the function which can get the object pointer. Then the methods
+in that library object is accessed.
+
+Here, the Magazine class is an abstract class with various magazine
+objects like Newsweek and Today deriving form it. The libraries are
+dynamically linked on demand. Thus, they can be changed on the fly
+and accessed with its new changes.
+
+The ACE_DLL class used in this example is an helper class for
+performing various operations on the library object.
+
+Compilation and Execution:
+-------------------------
+
+1. On POSIX/UNIX platforms:
+
+ First, build the test program, which you can do on UNIX as follows:
+
+ % make
+
+ Then run the test program:
+
+ % test_dll
+
+ to exercise the test.
+
+
+2. On NT or any Win32 platform:
+
+ Load Dll.dsw which contains Test_dll.dsp, Today.dsp and Newsweek.dsp.
+
+ Build each dsp such that you build Test_dll.dsp last.
+ This is because the test_dll.exe will be using Today.dll and Newsweek.dll.
+
+ Execute test_dll
+
+ and watch it run!
+
diff --git a/ACE/examples/DLL/Today.cpp b/ACE/examples/DLL/Today.cpp
new file mode 100644
index 00000000000..b80bfff2b0a
--- /dev/null
+++ b/ACE/examples/DLL/Today.cpp
@@ -0,0 +1,55 @@
+// $Id$
+
+#define ACE_BUILD_SVC_DLL
+
+#include "Today.h"
+#include "ace/Log_Msg.h"
+#include "ace/svc_export.h"
+#include "ace/OS_Memory.h"
+
+// Implementation of the abstract class method which describes the
+// magazine.
+
+void
+Today::title (void)
+{
+ ACE_DEBUG ((LM_DEBUG,
+ "Today: XML Special Apr 02\n"));
+}
+
+void *
+Today::operator new (size_t bytes)
+{
+ return ::new char[bytes];
+}
+#if defined (ACE_HAS_NEW_NOTHROW)
+void *
+Today::operator new (size_t bytes, const ACE_nothrow_t&)
+{
+ return ::new (ACE_nothrow) char[bytes];
+}
+#if !defined (ACE_LACKS_PLACEMENT_OPERATOR_DELETE)
+void
+Today::operator delete (void *p, const ACE_nothrow_t&) throw ()
+{
+ delete [] static_cast <char *> (p);
+}
+#endif /* ACE_LACKS_PLACEMENT_OPERATOR_DELETE */
+#endif
+void
+Today::operator delete (void *ptr)
+{
+ delete [] static_cast <char *> (ptr);
+}
+
+// Returns the pointer to the Today class.
+// The ACE_BUILD_SVC_DLL and ACE_Svc_Export directives are necessary to
+// take care of exporting the function for Win32 platforms.
+extern "C" ACE_Svc_Export Magazine *create_magazine (void);
+
+Magazine *create_magazine (void)
+{
+ Magazine *mag = 0;
+ ACE_NEW_RETURN (mag, Today, 0);
+ return mag;
+}
diff --git a/ACE/examples/DLL/Today.h b/ACE/examples/DLL/Today.h
new file mode 100644
index 00000000000..00c2d4b9c04
--- /dev/null
+++ b/ACE/examples/DLL/Today.h
@@ -0,0 +1,60 @@
+/* -*- C++ -*- */
+// $Id$
+
+// ===========================================================
+//
+// = LIBRARY
+// ACE_wrappers/examples/DLL
+//
+// = FILENAME
+// Today.h
+//
+// = DESCRIPTION
+// This class denotes the Today magazine which is derived from
+// Magazine.
+//
+// = AUTHOR
+// Kirthika Parameswaran <kirthika@cs.wustl.edu>
+//
+// ===========================================================
+
+#ifndef TODAY_H
+#define TODAY_H
+
+#include "ace/os_include/os_stddef.h"
+#include "ace/OS_Memory.h"
+#include "Magazine.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+class Today : public Magazine
+{
+ // = TITLE
+ // This is an derived class of Magazine.
+ //
+ // = DESCRIPTION
+ // Polymoriphism is exploited and an object pointer of Magazine
+ // is bound to the Today object at runtime.
+public:
+
+ // The virtual abstract class method which returns the title of the
+ // magazine.
+ void title (void);
+
+ // Overload the new/delete opertors so the object will be
+ // created/deleted using the memory allocator associated with the
+ // DLL/SO.
+ void *operator new (size_t bytes);
+#if defined (ACE_HAS_NEW_NOTHROW)
+ // Overloaded new operator, nothrow_t variant.
+ void *operator new (size_t bytes, const ACE_nothrow_t&);
+#if !defined (ACE_LACKS_PLACEMENT_OPERATOR_DELETE)
+ void operator delete (void *p, const ACE_nothrow_t&) throw ();
+#endif /* ACE_LACKS_PLACEMENT_OPERATOR_DELETE */
+#endif
+ void operator delete (void *ptr);
+};
+
+#endif /* TODAY_H */
diff --git a/ACE/examples/DLL/test_dll.cpp b/ACE/examples/DLL/test_dll.cpp
new file mode 100644
index 00000000000..49f385aff98
--- /dev/null
+++ b/ACE/examples/DLL/test_dll.cpp
@@ -0,0 +1,90 @@
+// $Id$
+
+// This program tests out how the various objects can be loaded
+// dynamically and method calls made on them.
+
+#include "Magazine.h"
+#include "ace/DLL.h"
+#include "ace/Auto_Ptr.h"
+#include "ace/Log_Msg.h"
+
+ACE_RCSID(DLL, test_dll, "$Id$")
+
+typedef Magazine* (*Magazine_Creator) (void);
+
+int
+ACE_TMAIN (int argc, ACE_TCHAR *argv[])
+{
+ ACE_UNUSED_ARG (argc);
+ ACE_UNUSED_ARG (argv);
+
+ ACE_DLL dll;
+
+ int retval = dll.open (ACE_TEXT("./") ACE_DLL_PREFIX ACE_TEXT("DLL_Today"));
+
+ if (retval != 0)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%p",
+ "dll.open"),
+ -1);
+ Magazine_Creator mc;
+
+ // Cast the void* to non-pointer type first - it's not legal to
+ // cast a pointer-to-object directly to a pointer-to-function.
+ void *void_ptr = dll.symbol (ACE_TEXT ("create_magazine"));
+ ptrdiff_t tmp = reinterpret_cast<ptrdiff_t> (void_ptr);
+ mc = reinterpret_cast<Magazine_Creator> (tmp);
+
+ if (mc == 0)
+ {
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%p",
+ "dll.symbol"),
+ -1);
+ }
+
+ {
+ auto_ptr <Magazine> magazine (mc ());
+
+ magazine->title ();
+ }
+
+ dll.close ();
+
+ // The other library is now loaded on demand.
+
+ retval = dll.open (ACE_DLL_PREFIX ACE_TEXT ("DLL_Newsweek"));
+
+ if (retval != 0)
+ {
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%p",
+ "dll.open"),
+ -1);
+ }
+
+ // Cast the void* to non-pointer type first - it's not legal to
+ // cast a pointer-to-object directly to a pointer-to-function.
+ void_ptr = dll.symbol (ACE_TEXT ("create_magazine"));
+ tmp = reinterpret_cast<ptrdiff_t> (void_ptr);
+ mc = reinterpret_cast<Magazine_Creator> (tmp);
+
+ if (mc == 0)
+ {
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%p",
+ "dll.symbol"),
+ -1);
+ }
+
+ {
+ auto_ptr <Magazine> magazine (mc ());
+
+ magazine->title ();
+ }
+
+ dll.close ();
+
+ return 0;
+}
+
diff --git a/ACE/examples/Export/.cvsignore b/ACE/examples/Export/.cvsignore
new file mode 100644
index 00000000000..dec2cbe1fa3
--- /dev/null
+++ b/ACE/examples/Export/.cvsignore
@@ -0,0 +1,2 @@
+test
+test
diff --git a/ACE/examples/Export/Export.mpc b/ACE/examples/Export/Export.mpc
new file mode 100644
index 00000000000..51edc145591
--- /dev/null
+++ b/ACE/examples/Export/Export.mpc
@@ -0,0 +1,19 @@
+// -*- MPC -*-
+// $Id$
+
+project(*Lib) : acelib {
+ sharedname = Export_Lib
+ dynamicflags += TEST_BUILD_DLL
+ Source_Files {
+ dll.cpp
+ }
+}
+
+project(*test) : aceexe {
+ exename = test
+ after += *Lib
+ libs += Export_Lib
+ Source_Files {
+ test.cpp
+ }
+}
diff --git a/ACE/examples/Export/Makefile.am b/ACE/examples/Export/Makefile.am
new file mode 100644
index 00000000000..74baf4baf66
--- /dev/null
+++ b/ACE/examples/Export/Makefile.am
@@ -0,0 +1,51 @@
+## Process this file with automake to create Makefile.in
+##
+## $Id$
+##
+## This file was generated by MPC. Any changes made directly to
+## this file will be lost the next time it is generated.
+##
+## MPC Command:
+## /acebuilds/ACE_wrappers-repository/bin/mwc.pl -include /acebuilds/MPC/config -include /acebuilds/MPC/templates -feature_file /acebuilds/ACE_wrappers-repository/local.features -noreldefs -type automake -exclude build,Kokyu
+
+ACE_BUILDDIR = $(top_builddir)
+ACE_ROOT = $(top_srcdir)
+
+## Makefile.Export_Lib.am
+
+noinst_LTLIBRARIES = libExport_Lib.la
+
+libExport_Lib_la_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR) \
+ -DTEST_BUILD_DLL
+
+libExport_Lib_la_SOURCES = \
+ dll.cpp
+
+noinst_HEADERS = \
+ dll.h
+
+## Makefile.Export_Test.am
+noinst_PROGRAMS = test
+
+test_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+test_SOURCES = \
+ test.cpp \
+ dll.h \
+ test_export.h
+
+test_LDADD = \
+ libExport_Lib.la \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Clean up template repositories, etc.
+clean-local:
+ -rm -f *~ *.bak *.rpo *.sym lib*.*_pure_* core core.*
+ -rm -f gcctemp.c gcctemp so_locations *.ics
+ -rm -rf cxx_repository ptrepository ti_files
+ -rm -rf templateregistry ir.out
+ -rm -rf ptrepository SunWS_cache Templates.DB
diff --git a/ACE/examples/Export/README b/ACE/examples/Export/README
new file mode 100644
index 00000000000..83fc3108d50
--- /dev/null
+++ b/ACE/examples/Export/README
@@ -0,0 +1,7 @@
+$Id$
+
+The Export example is just an example that both shows off and tests
+the macros created by generate_export_file.pl (or the earlier
+GenExportH.bat). These macros are used to properly export functions
+and classes from a Win32 DLL. On other platforms these macros expand
+to nothing (since shared objects just export everything).
diff --git a/ACE/examples/Export/dll.cpp b/ACE/examples/Export/dll.cpp
new file mode 100644
index 00000000000..07705db9d59
--- /dev/null
+++ b/ACE/examples/Export/dll.cpp
@@ -0,0 +1,27 @@
+// $Id$
+#include "dll.h"
+
+int test_variable = 0;
+
+int
+test_function ()
+{
+ test_variable = RETVAL;
+ return RETVAL;
+}
+
+int
+test_class::method ()
+{
+ return RETVAL;
+}
+
+test_class *
+get_dll_singleton ()
+{
+ return TEST_SINGLETON::instance ();
+}
+
+#if defined (ACE_HAS_EXPLICIT_STATIC_TEMPLATE_MEMBER_INSTANTIATION)
+template ACE_Singleton<test_class, ACE_Null_Mutex> *ACE_Singleton<test_class, ACE_Null_Mutex>::singleton_;
+#endif /* ACE_HAS_EXPLICIT_STATIC_TEMPLATE_MEMBER_INSTANTIATION */
diff --git a/ACE/examples/Export/dll.h b/ACE/examples/Export/dll.h
new file mode 100644
index 00000000000..b07d3fe1cd8
--- /dev/null
+++ b/ACE/examples/Export/dll.h
@@ -0,0 +1,69 @@
+// $Id$
+
+// To use the export macros with a DLL, a file will need to be
+// created (see ACE_wrapper/bin/generate_export_file.pl) and
+// included. This file defines Test_Export (and the
+// TEST_SINGLETON_* macros).
+#include "test_export.h"
+
+#include "ace/Singleton.h"
+#include "ace/Null_Mutex.h"
+
+#define RETVAL 42
+
+// To expose a function outside of a DLL, use the *_Export
+// at the beginning of the function declaration.
+
+Test_Export int test_function ();
+
+// To expose data, put use the *Export at the beginning
+// of the variable declaration. The extern is required when
+// building static libraries.
+
+extern Test_Export int test_variable;
+
+// To expose a class, put the *_Export between "class"
+// and the class name.
+
+class Test_Export test_class
+{
+public:
+ int method ();
+};
+
+// ACE_Singleton and its relatives are special cases. The problem is
+// that ACE_Singleton is a template. If the singleton is used in both
+// the DLL and the executable linking the DLL, then two instances of
+// the singleton will be used (which defeats the purpose of a Singleton).
+//
+// This occurs because the ACE_Singleton template is expanded in both
+// places because Visual C++ and Borland C++ do this automatically by
+// including the template source. This in turn creates two copies of
+// the static member variable.
+//
+// So to get around this problem, the *_SINGLETON_DECLARE macro is
+// used to instruct the compiler to not create the second copy in the
+// program. This macro solution does not work for Borland C++, so for
+// this compiler you must explicitly disable the template instantiation
+// using a #pragma (or use the other workaround below).
+//
+// Another workaround for this is to not to expose the Singleton itself
+// to the outside world, but to instead supply a function or static
+// member function that returns the singleton to the executable
+// (like get_dll_singleton () does below).
+
+#if defined (__BORLANDC__)
+# if !defined (TEST_BUILD_DLL)
+# pragma option push -Jgx
+# endif
+#endif
+TEST_SINGLETON_DECLARE (ACE_Singleton, test_class, ACE_Null_Mutex)
+#if defined (__BORLANDC__)
+# if !defined (TEST_BUILD_DLL)
+# pragma option pop
+# endif
+#endif
+
+typedef ACE_Singleton<test_class, ACE_Null_Mutex> TEST_SINGLETON;
+
+Test_Export test_class *get_dll_singleton ();
diff --git a/ACE/examples/Export/run_test.pl b/ACE/examples/Export/run_test.pl
new file mode 100755
index 00000000000..7c84078d8ff
--- /dev/null
+++ b/ACE/examples/Export/run_test.pl
@@ -0,0 +1,17 @@
+eval '(exit $?0)' && eval 'exec perl -S $0 ${1+"$@"}'
+ & eval 'exec perl -S $0 $argv:q'
+ if 0;
+
+# $Id$
+# -*- perl -*-
+
+use lib "../../bin";
+use PerlACE::Run_Test;
+
+$TEST = new PerlACE::Process ("test");
+
+$status = $TEST->SpawnWaitKill (20);
+
+$status = 1 if ($status < 0);
+
+exit $status;
diff --git a/ACE/examples/Export/test.cpp b/ACE/examples/Export/test.cpp
new file mode 100644
index 00000000000..c04f2998e66
--- /dev/null
+++ b/ACE/examples/Export/test.cpp
@@ -0,0 +1,64 @@
+// $Id$
+
+#include "dll.h"
+#include <ace/streams.h>
+
+int
+ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ int failure_count = 0;
+ test_class my_test_class;
+
+ // Tet out the export of a class. I don't see
+ // How this can fail at runtime (rather it would
+ // probably give link errors), but just in case...
+
+ cout << "Method Test: ";
+ if (my_test_class.method () != RETVAL)
+ {
+ cout << "Failed" << endl;
+ ++failure_count;
+ }
+ else
+ cout << "Succeeded" << endl;
+
+ // Test out the export of a function. Like above,
+ // I don't know how this can fail at runtime.
+
+ cout << "Function Test: ";
+ if (test_function () != RETVAL)
+ {
+ cout << "Failed" << endl;
+ ++failure_count;
+ }
+ else
+ cout << "Succeeded" << endl;
+
+ // Also test out the export of data.
+
+ cout << "Variable Test: ";
+ if (test_variable != RETVAL)
+ {
+ cout << "Failed" << endl;
+ ++failure_count;
+ }
+ else
+ cout << "Succeeded" << endl;
+
+
+ // Test out the ACE_Singleton export by checking to see
+ // that we have the same instance pointer as the DLL does.
+ // This can fail at runtime.
+
+ cout << "Singleton Test: ";
+ if (TEST_SINGLETON::instance () != get_dll_singleton ())
+ {
+ cout << "Failed" << endl;
+ ++failure_count;
+ }
+ else
+ cout << "Succeeded" << endl;
+
+ // Return the number of failures
+ return failure_count;
+}
diff --git a/ACE/examples/Export/test_export.h b/ACE/examples/Export/test_export.h
new file mode 100644
index 00000000000..45ee8296d22
--- /dev/null
+++ b/ACE/examples/Export/test_export.h
@@ -0,0 +1,44 @@
+// -*- C++ -*-
+// $Id$
+// Definition for Win32 Export directives.
+// This file is generated automatically by
+// generate_export_file.pl
+// ------------------------------
+#if !defined (TEST_EXPORT_H)
+#define TEST_EXPORT_H
+
+#include "ace/config-all.h"
+
+#if defined (ACE_AS_STATIC_LIBS) && !defined (TEST_HAS_DLL)
+# define TEST_HAS_DLL 0
+#endif /* ACE_AS_STATIC_LIBS && ! TEST_HAS_DLL */
+
+#if !defined (TEST_HAS_DLL)
+#define TEST_HAS_DLL 1
+#endif /* ! TEST_HAS_DLL */
+
+#if defined (TEST_HAS_DLL)
+# if (TEST_HAS_DLL == 1)
+# if defined (TEST_BUILD_DLL)
+# define Test_Export ACE_Proper_Export_Flag
+# define TEST_SINGLETON_DECLARATION(T) ACE_EXPORT_SINGLETON_DECLARATION (T)
+# define TEST_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) ACE_EXPORT_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK)
+# else
+# define Test_Export ACE_Proper_Import_Flag
+# define TEST_SINGLETON_DECLARATION(T) ACE_IMPORT_SINGLETON_DECLARATION (T)
+# define TEST_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) ACE_IMPORT_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK)
+# endif /* TEST_BUILD_DLL */
+# else
+# define Test_Export
+# define TEST_SINGLETON_DECLARATION(T)
+# define TEST_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK)
+# endif /* ! TEST_HAS_DLL == 1 */
+#else
+# define Test_Export
+# define TEST_SINGLETON_DECLARATION(T)
+# define TEST_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK)
+#endif /* TEST_HAS_DLL */
+
+#endif /* TEST_EXPORT_H */
+
+// End of auto generated file.
diff --git a/ACE/examples/IOStream/Makefile.am b/ACE/examples/IOStream/Makefile.am
new file mode 100644
index 00000000000..0a99932ce34
--- /dev/null
+++ b/ACE/examples/IOStream/Makefile.am
@@ -0,0 +1,14 @@
+## Process this file with automake to create Makefile.in
+##
+## $Id$
+##
+## This file was generated by MPC. Any changes made directly to
+## this file will be lost the next time it is generated.
+##
+## MPC Command:
+## /acebuilds/ACE_wrappers-repository/bin/mwc.pl -include /acebuilds/MPC/config -include /acebuilds/MPC/templates -feature_file /acebuilds/ACE_wrappers-repository/local.features -noreldefs -type automake -exclude build,Kokyu
+
+SUBDIRS = \
+ client \
+ server
+
diff --git a/ACE/examples/IOStream/README b/ACE/examples/IOStream/README
new file mode 100644
index 00000000000..ab215fc779d
--- /dev/null
+++ b/ACE/examples/IOStream/README
@@ -0,0 +1,22 @@
+This example illustrates the use of the ACE_IOStream and
+ACE_Streambuf_T templates to create an object based on ACE_*_Stream
+classes. These classes provide C++ iostream functionality across a
+socket.
+
+To run the tests simply build the executables in the client and server
+directories and then do the following in separate windows:
+
+# Window 1
+% server/iostream_server
+(10049) starting up daemon
+
+# Window 2
+% client/iostream_client
+(10049) starting handler 456d0
+(10049) Client sent:
+ (1) (2.3)
+(10051) Server sent:
+ (1) (2.3)
+(10049) connection closed
+(10049) shutting down handler 456d0
+(10049) shutting down server daemon
diff --git a/ACE/examples/IOStream/client/.cvsignore b/ACE/examples/IOStream/client/.cvsignore
new file mode 100644
index 00000000000..e5eeb0703df
--- /dev/null
+++ b/ACE/examples/IOStream/client/.cvsignore
@@ -0,0 +1,2 @@
+iostream_client
+iostream_client
diff --git a/ACE/examples/IOStream/client/IOStream_Client.mpc b/ACE/examples/IOStream/client/IOStream_Client.mpc
new file mode 100644
index 00000000000..ca6b8ee6622
--- /dev/null
+++ b/ACE/examples/IOStream/client/IOStream_Client.mpc
@@ -0,0 +1,5 @@
+// -*- MPC -*-
+// $Id$
+
+project : aceexe {
+} \ No newline at end of file
diff --git a/ACE/examples/IOStream/client/Makefile.am b/ACE/examples/IOStream/client/Makefile.am
new file mode 100644
index 00000000000..e1225bbb6d5
--- /dev/null
+++ b/ACE/examples/IOStream/client/Makefile.am
@@ -0,0 +1,30 @@
+## Process this file with automake to create Makefile.in
+##
+## $Id$
+##
+## This file was generated by MPC. Any changes made directly to
+## this file will be lost the next time it is generated.
+##
+## MPC Command:
+## /acebuilds/ACE_wrappers-repository/bin/mwc.pl -include /acebuilds/MPC/config -include /acebuilds/MPC/templates -feature_file /acebuilds/ACE_wrappers-repository/local.features -noreldefs -type automake -exclude build,Kokyu
+
+ACE_BUILDDIR = $(top_builddir)
+ACE_ROOT = $(top_srcdir)
+
+## Makefile.IOStream_Client.am
+noinst_LTLIBRARIES = libIOStream_Client.la
+
+libIOStream_Client_la_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+libIOStream_Client_la_SOURCES = \
+ iostream_client.cpp
+
+## Clean up template repositories, etc.
+clean-local:
+ -rm -f *~ *.bak *.rpo *.sym lib*.*_pure_* core core.*
+ -rm -f gcctemp.c gcctemp so_locations *.ics
+ -rm -rf cxx_repository ptrepository ti_files
+ -rm -rf templateregistry ir.out
+ -rm -rf ptrepository SunWS_cache Templates.DB
diff --git a/ACE/examples/IOStream/client/iostream_client.cpp b/ACE/examples/IOStream/client/iostream_client.cpp
new file mode 100644
index 00000000000..e8ddedf9b44
--- /dev/null
+++ b/ACE/examples/IOStream/client/iostream_client.cpp
@@ -0,0 +1,71 @@
+// $Id$
+
+#include "ace/SOCK_Connector.h"
+#include "ace/IOStream.h"
+#include "ace/Log_Msg.h"
+#include "ace/OS_NS_stdlib.h"
+#include "ace/OS_NS_unistd.h"
+
+ACE_RCSID (client,
+ iostream_client,
+ "$Id$")
+
+// This client is a simple example of using the ACE_IOStream and
+// ACE_Streambuf_T templates to create an object based on ACE_*_Stream
+// classes, which mimic a C++ iostream.
+
+int
+ACE_TMAIN (int argc, ACE_TCHAR *argv[])
+{
+#if !defined (ACE_LACKS_ACE_IOSTREAM)
+ const ACE_TCHAR *server_host = argc > 1 ? argv[1] : ACE_DEFAULT_SERVER_HOST;
+ u_short server_port = argc > 2 ? ACE_OS::atoi (argv[2]) : ACE_DEFAULT_SERVER_PORT;
+
+ ACE_IOStream<ACE_SOCK_Stream> server;
+ ACE_SOCK_Connector connector;
+ ACE_INET_Addr addr (server_port,
+ server_host);
+
+ if (connector.connect (server, addr) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%p\n",
+ "open"),
+ -1);
+
+ // Buffer up some things to send to the server.
+ server << "1 2.3 testing" << endl;
+
+ int i;
+ float f;
+
+#if defined (ACE_HAS_STRING_CLASS)
+ ACE_IOStream_String s1;
+ ACE_IOStream_String s2;
+ server >> s1 >> i >> f >> s2;
+
+ cerr << "Server said:\n\t";
+ cerr << s1 << " ";
+ cerr << i << " ";
+ cerr << f << " ";
+ cerr << s2 << endl;
+#else
+ server >> i >> f;
+
+ cerr << "(" << ACE_OS::getpid () << ") Server sent:\n\t";
+ cerr << "(" << i << ") ";
+ cerr << "(" << f << ")" << endl;
+#endif /* ACE_HAS_STRING_CLASS */
+
+ if (server.close () == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%p\n",
+ "close"),
+ -1);
+#else
+ ACE_UNUSED_ARG (argc);
+ ACE_UNUSED_ARG (argv);
+ ACE_ERROR ((LM_ERROR, "ACE_IOSTREAM not supported on this platform\n"));
+#endif /* !ACE_LACKS_ACE_IOSTREAM */
+ return 0;
+}
+
diff --git a/ACE/examples/IOStream/server/.cvsignore b/ACE/examples/IOStream/server/.cvsignore
new file mode 100644
index 00000000000..e37ecb3f31b
--- /dev/null
+++ b/ACE/examples/IOStream/server/.cvsignore
@@ -0,0 +1,2 @@
+iostream_server
+iostream_server
diff --git a/ACE/examples/IOStream/server/IOStream_Server.mpc b/ACE/examples/IOStream/server/IOStream_Server.mpc
new file mode 100644
index 00000000000..ca6b8ee6622
--- /dev/null
+++ b/ACE/examples/IOStream/server/IOStream_Server.mpc
@@ -0,0 +1,5 @@
+// -*- MPC -*-
+// $Id$
+
+project : aceexe {
+} \ No newline at end of file
diff --git a/ACE/examples/IOStream/server/Makefile.am b/ACE/examples/IOStream/server/Makefile.am
new file mode 100644
index 00000000000..8b72a1adb62
--- /dev/null
+++ b/ACE/examples/IOStream/server/Makefile.am
@@ -0,0 +1,33 @@
+## Process this file with automake to create Makefile.in
+##
+## $Id$
+##
+## This file was generated by MPC. Any changes made directly to
+## this file will be lost the next time it is generated.
+##
+## MPC Command:
+## /acebuilds/ACE_wrappers-repository/bin/mwc.pl -include /acebuilds/MPC/config -include /acebuilds/MPC/templates -feature_file /acebuilds/ACE_wrappers-repository/local.features -noreldefs -type automake -exclude build,Kokyu
+
+ACE_BUILDDIR = $(top_builddir)
+ACE_ROOT = $(top_srcdir)
+
+## Makefile.IOStream_Server.am
+noinst_LTLIBRARIES = libIOStream_Server.la
+
+libIOStream_Server_la_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+libIOStream_Server_la_SOURCES = \
+ iostream_server.cpp
+
+noinst_HEADERS = \
+ iostream_server.h
+
+## Clean up template repositories, etc.
+clean-local:
+ -rm -f *~ *.bak *.rpo *.sym lib*.*_pure_* core core.*
+ -rm -f gcctemp.c gcctemp so_locations *.ics
+ -rm -rf cxx_repository ptrepository ti_files
+ -rm -rf templateregistry ir.out
+ -rm -rf ptrepository SunWS_cache Templates.DB
diff --git a/ACE/examples/IOStream/server/iostream_server.cpp b/ACE/examples/IOStream/server/iostream_server.cpp
new file mode 100644
index 00000000000..656b432a579
--- /dev/null
+++ b/ACE/examples/IOStream/server/iostream_server.cpp
@@ -0,0 +1,132 @@
+// $Id$
+
+// This is a simple example of using the ACE_IOStream and
+// ACE_Streambuf_T templates to create an object based on ACE_*_Stream
+// classes, which mimic a C++ iostream.
+
+#include "ace/Acceptor.h"
+#include "ace/SOCK_Acceptor.h"
+#include "ace/Service_Config.h"
+#include "ace/Signal.h"
+
+#include "iostream_server.h"
+#include "ace/OS_NS_unistd.h"
+
+ACE_RCSID(server, iostream_server, "$Id$")
+
+#if !defined (ACE_LACKS_ACE_IOSTREAM)
+
+int
+Handler::open (void *)
+{
+ if (this->reactor ()->register_handler (this,
+ ACE_Event_Handler::READ_MASK) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "registering connection handler with ACE_Reactor\n"),
+ -1);
+ return 0;
+}
+
+Handler::Handler (void)
+{
+ ACE_DEBUG ((LM_DEBUG, "(%P) starting handler %x\n", this));
+}
+
+Handler::~Handler (void)
+{
+ ACE_DEBUG ((LM_DEBUG, "(%P) shutting down handler %x\n", this));
+ ACE_Reactor::end_event_loop ();
+}
+
+int
+Handler::handle_input (ACE_HANDLE)
+{
+ int i;
+ float f;
+
+ // Check to see if the socket is closed down.
+ if (this->peer ().eof ())
+ ACE_ERROR_RETURN ((LM_ERROR, "(%P) connection closed\n"), -1);
+
+#if defined (ACE_HAS_STRING_CLASS)
+ ACE_IOStream_String s;
+
+ if (!(this->peer () >> i >> f >> s))
+ ACE_ERROR_RETURN ((LM_ERROR, "(%P) %p\n", "error getting data"), -1);
+
+ cerr << "(" << ACE_OS::getpid () << ") Client sent:\n\t";
+ cerr << "(" << i << ") (" << f << ") (" << s << ")" << endl ;
+
+ if (!(this->peer () << "Received: " << i << " " << f << " " << s << endl))
+ ACE_ERROR_RETURN ((LM_ERROR, "(%P) %p\n", "error sending data"), -1);
+
+#else
+ if (!(this->peer () >> i >> f))
+ ACE_ERROR_RETURN ((LM_ERROR, "(%P) %p\n", "error getting data"), -1);
+
+ cerr << "(" << ACE_OS::getpid () << ") Client sent:\n\t";
+ cerr << "(" << i << ") (" << f << ")" << endl;
+
+ if (!(this->peer () << i << " " << f << endl))
+ ACE_ERROR_RETURN ((LM_ERROR, "(%P) %p\n", "error sending data"), -1);
+#endif /* ACE_HAS_STRING_CLASS */
+
+ // In order to flush the output to the peer, we have to use the sync
+ // () function. Some iostreams implementations let us use a 'flush'
+ // function much like the 'endl' function.
+
+ // this->peer ().sync ();
+ return 0;
+}
+
+// Create a factory object that will accept new connection requests
+// and create handler objects for us.
+
+typedef ACE_Acceptor<Handler, ACE_SOCK_ACCEPTOR> IOStream_Acceptor;
+#endif /* !ACE_LACKS_ACE_IOSTREAM */
+
+int
+ACE_TMAIN (int argc, ACE_TCHAR *argv [])
+{
+#if !defined (ACE_LACKS_ACE_IOSTREAM)
+ ACE_Service_Config daemon;
+
+ // Create an adapter to end the event loop.
+ ACE_Sig_Adapter sa ((ACE_Sig_Handler_Ex) ACE_Reactor::end_event_loop);
+
+ ACE_Sig_Set sig_set;
+ sig_set.sig_add (SIGINT);
+ sig_set.sig_add (SIGQUIT);
+
+ // Register ourselves to receive SIGINT and SIGQUIT so we can shut
+ // down gracefully via signals.
+ if (ACE_Reactor::instance ()->register_handler (sig_set,
+ &sa) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, "%p\n"), -1);
+
+ IOStream_Acceptor peer_acceptor;
+
+ ACE_INET_Addr addr (argc > 1 ? ACE_OS::atoi (argv[1]) : ACE_DEFAULT_SERVER_PORT);
+
+ if (peer_acceptor.open (addr) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%p\n",
+ "open"),
+ -1);
+
+ ACE_DEBUG ((LM_DEBUG,
+ "(%P) starting up daemon\n"));
+
+ ACE_Reactor::run_event_loop ();
+
+ ACE_DEBUG ((LM_DEBUG,
+ "(%P) shutting down server daemon\n"));
+
+#else
+ ACE_UNUSED_ARG (argc);
+ ACE_UNUSED_ARG (argv);
+ ACE_ERROR ((LM_ERROR, "ACE_IOSTREAM not supported on this platform\n"));
+#endif /* !ACE_LACKS_ACE_IOSTREAM */
+ return 0;
+}
+
diff --git a/ACE/examples/IOStream/server/iostream_server.h b/ACE/examples/IOStream/server/iostream_server.h
new file mode 100644
index 00000000000..e5f4cbd63b9
--- /dev/null
+++ b/ACE/examples/IOStream/server/iostream_server.h
@@ -0,0 +1,53 @@
+// $Id$
+
+// This file defines the class needed for iostream_server.cpp - it's a separate
+// file to satisfy IBM's xlC template instantiation.
+
+#ifndef __IOSTREAM_SERVER_H
+#define __IOSTREAM_SERVER_H
+
+#include "ace/INET_Addr.h"
+#include "ace/IOStream.h"
+#include "ace/SOCK_Stream.h"
+#include "ace/Svc_Handler.h"
+
+#if !defined (ACE_LACKS_ACE_IOSTREAM)
+
+// Declare a new type which will case an ACE_SOCK_Stream to behave
+// like an iostream. The new ACE_SOCK_IOStream type can be used
+// anywhere an ACE_SOCK_Stream is used.
+
+typedef ACE_IOStream<ACE_SOCK_Stream> ACE_SOCK_IOStream;
+
+// Need to handle brain-dead C++ compilers.
+#if defined (ACE_HAS_TEMPLATE_TYPEDEFS)
+#define ACE_SOCK_IOSTREAM ACE_SOCK_IOStream
+#else
+#define ACE_SOCK_IOSTREAM ACE_SOCK_IOStream, ACE_INET_Addr
+#endif /* ACE_HAS_TYPENAME_KEYWORD */
+
+class Handler : public ACE_Svc_Handler<ACE_SOCK_IOSTREAM, ACE_NULL_SYNCH>
+ // = TITLE
+ // Extend the <ACE_Svc_Handler> template to do our bidding.
+ //
+ // = DESCRIPTION
+ // Create an <ACE_Svc_Handler> object based on our
+ // iostream/SOCK_Stream hybrid. All of this is fairly standard
+ // until we get to the <handle_input> where we begin using the
+ // iostream characteristics of the peer.
+{
+public:
+ // = Initialization and termination methods.
+ Handler (void);
+ ~Handler (void);
+
+ // = <Svc_Handler> hooks.
+ virtual int open (void *);
+
+ // = <Event_Handler> hooks.
+ virtual int handle_input (ACE_HANDLE);
+};
+
+#endif /* ACE_LACKS_ACE_IOSTREAM */
+
+#endif /* __IOSTREAM_SERVER_H */
diff --git a/ACE/examples/IPC_SAP/ATM_SAP/.cvsignore b/ACE/examples/IPC_SAP/ATM_SAP/.cvsignore
new file mode 100644
index 00000000000..955ffdc75d5
--- /dev/null
+++ b/ACE/examples/IPC_SAP/ATM_SAP/.cvsignore
@@ -0,0 +1,4 @@
+client
+client
+server
+server
diff --git a/ACE/examples/IPC_SAP/ATM_SAP/CPP-client.cpp b/ACE/examples/IPC_SAP/ATM_SAP/CPP-client.cpp
new file mode 100644
index 00000000000..cbe2c00ae5c
--- /dev/null
+++ b/ACE/examples/IPC_SAP/ATM_SAP/CPP-client.cpp
@@ -0,0 +1,202 @@
+// $Id$
+
+#include "ace/OS_main.h"
+#include "ace/ATM_Connector.h"
+#include "ace/ATM_Addr.h"
+#include "ace/High_Res_Timer.h"
+#include "ace/Log_Msg.h"
+
+ACE_RCSID(ATM_SAP, CPP_client, "$Id$")
+
+#if defined (ACE_HAS_ATM)
+
+#define MAX_LEAVES 32
+
+/* ACE_ATM Client */
+
+int ACE_TMAIN (int argc, ACE_TCHAR *argv[])
+{
+ if ( argc < 2 )
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Usage: %s <rate> <PDU> <session> <host> <selector> [ host sel ] ...\n"
+ "\tUse 0 for default values\n",
+ argv[0]),
+ 1);
+
+ int rate = ACE_OS::atoi( argv[ 1 ]);
+ rate = ( rate != 0 ) ? rate : 170000;
+ int pdu_size = ACE_OS::atoi( argv[ 2 ]) * 1024;
+ pdu_size = ( pdu_size != 0 ) ? pdu_size : 8192;
+ int session = ACE_OS::atoi( argv[ 3 ]);
+ session = ( session != 0 ) ? session : 100;
+
+ ACE_OS::printf( "ATM_Client: rate: %d c/s, PDU: %dB, session: %d pkts\n",
+ rate, pdu_size, session );
+
+ // Record all hosts/selectors
+ ACE_ATM_Addr hosts[ MAX_LEAVES ];
+ int num_leaves = argc / 2 - 2;
+
+ ACE_OS::printf( "ATM_Client: Connecting to ...\n" );
+ for ( int i = 0; i < num_leaves; i++ ) {
+ hosts[ i ].set( argv[ i*2 + 4 ],
+ ( argv[ i*2 + 5 ] != 0 )
+ ? ACE_OS::atoi( argv[ i*2 + 5 ]) : ACE_ATM_Addr::DEFAULT_SELECTOR );
+ ACE_OS::printf( "ATM_Client: leaf: %s (%s), sel: %d\n",
+ argv[ i*2 + 4 ],
+ hosts[ i ].addr_to_string(),
+ hosts[ i ].get_selector());
+ }
+
+ // The timeout really gets ignored since FORE's drivers don't work when
+ // ioctl or fcntl calls are made on the transport id/file descriptor
+ int timeout = ACE_DEFAULT_TIMEOUT;
+ char buf[BUFSIZ];
+ ACE_ATM_Stream atm_stream;
+
+ char hostname[ MAXNAMELEN ];
+ ACE_OS::hostname( hostname, MAXNAMELEN );
+ ACE_ATM_Addr local_addr( hostname, hosts[ 0 ].get_selector());
+
+ ACE_OS::printf( "ATM_Client: local host: %s(%s)\n",
+ hostname, local_addr.addr_to_string());
+
+ // In order to construct connections options the file handle is
+ // needed. Therefore, we need to open the ATM_Stream before we
+ // construct the options.
+ ACE_OS::printf( "ATM_Client: to open a stream\n" );
+ if (atm_stream.open () == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%p\n",
+ "open failed"),
+ 1);
+
+ ACE_DEBUG ((LM_DEBUG,
+ "ATM_Client: starting non-blocking connection\n"));
+
+ // Initiate timed, non-blocking connection with server.
+ ACE_ATM_Connector con;
+
+ // Construct QoS options - currently FORE only supports bandwidth
+ ACE_OS::printf( "ATM_Client: specify cell rate at %d c/s\n", rate );
+ ACE_ATM_QoS qos;
+ qos.set_rate(atm_stream.get_handle (),
+ rate,
+ ACE_ATM_QoS::OPT_FLAGS_CPID);
+
+ if ( num_leaves == 1 ) {
+ // Point-to-point connection
+ // Not sure why but reuse_addr set to true/1 causes problems for
+ // FORE/XTI/ATM - this is now handled in ACE_ATM_Connector::connect()
+ ACE_OS::printf( "ATM_Client: to open a connection \n" );
+ ACE_ATM_Params params = ACE_ATM_Params();
+ if (con.connect (atm_stream,
+ hosts[ 0 ],
+ params,
+ qos,
+ (ACE_Time_Value *) &ACE_Time_Value::zero,
+ local_addr,
+ 0,
+ 0 ) == -1) {
+ if (errno != EWOULDBLOCK)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%p\n",
+ "ATM_Client: connection failed"),
+ 1);
+
+ ACE_DEBUG ((LM_DEBUG,
+ "ATM_Client: starting timed connection\n"));
+
+ // Check if non-blocking connection is in progress, and wait up
+ // to timeout seconds for it to complete.
+ ACE_Time_Value tv (timeout);
+
+ ACE_OS::printf( "ATM_Client: connection completed\n" );
+ if (con.complete (atm_stream,
+ &hosts[ 0 ],
+ &tv) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%p\n",
+ "ATM_Client: connection failed"),
+ 1);
+ else
+ ACE_DEBUG ((LM_DEBUG,
+ "ATM_Client: connected to %s\n",
+ hosts[ 0 ].addr_to_string()));
+ }
+ } else {
+ // Point-to-multipoint connection
+ for ( int i = 0; i < num_leaves; i++ ) {
+ con.add_leaf( atm_stream,
+ hosts[ i ],
+ i,
+ NULL );
+
+ }
+ } /* if num_leaves == 1 */
+
+ ACE_UINT16 vpi, vci;
+ atm_stream.get_vpi_vci(vpi, vci);
+ ACE_DEBUG ((LM_DEBUG,
+ "ATM_Client: connected to VPI %d VCI %d\n",
+ vpi, vci));
+
+ // Send data to server (correctly handles "incomplete writes").
+
+ int s_bytes;
+ int total;
+ int xmit = 0;
+ ACE_High_Res_Timer timer;
+ ACE_Time_Value elapsed;
+ double real_time;
+ double actual_rate;
+
+ for ( ;; ) {
+ total = 0;
+
+ timer.start_incr();
+
+ for ( ;; ) {
+ s_bytes = atm_stream.send_n( buf, BUFSIZ, 0 );
+ if ( s_bytes == -1 )
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%p\n",
+ "send_n"),
+ 1);
+
+ total += s_bytes;
+
+ if ( total >= session * pdu_size )
+ break;
+ }
+
+ timer.stop_incr();
+ timer.elapsed_time_incr( elapsed );
+ real_time = elapsed.sec() * ACE_ONE_SECOND_IN_USECS + elapsed.usec();
+ xmit += total;
+ actual_rate = ( double )xmit * ( double )8 / real_time;
+
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("(%t) bytes = %d, usec = %f, rate = %0.00f Mbps\n"),
+ xmit,
+ real_time,
+ actual_rate < 0 ? 0 : actual_rate ));
+ }
+
+ // Explicitly close the connection.
+ ACE_OS::printf( "ATM_Client: close connection\n" );
+ if (atm_stream.close () == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%p\n",
+ "close"),
+ -1);
+ return 0;
+}
+#else
+int ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "your platform isn't configured to support ATM\n"),
+ 1);
+}
+#endif /* ACE_HAS_ATM */
diff --git a/ACE/examples/IPC_SAP/ATM_SAP/CPP-server.cpp b/ACE/examples/IPC_SAP/ATM_SAP/CPP-server.cpp
new file mode 100644
index 00000000000..8cf6e9c9c92
--- /dev/null
+++ b/ACE/examples/IPC_SAP/ATM_SAP/CPP-server.cpp
@@ -0,0 +1,156 @@
+// $Id$
+
+#include "ace/OS_main.h"
+#include "ace/ATM_Acceptor.h"
+#include "ace/ATM_Addr.h"
+#include "ace/High_Res_Timer.h"
+#include "ace/Log_Msg.h"
+
+ACE_RCSID(ATM_SAP, CPP_ATM_server, "$Id$")
+
+#if defined (ACE_HAS_ATM)
+// ACE_ATM Server
+
+int
+ACE_TMAIN (int argc, ACE_TCHAR *argv[])
+{
+ ACE_Time_Value timeout (ACE_DEFAULT_TIMEOUT);
+
+ //unsigned char selector = ACE_ATM_Addr::DEFAULT_SELECTOR;
+ //int selector_specified = 0;
+
+ if (argc > 2)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Usage: %s [selector]\n",
+ argv[0]),
+ 1);
+
+ // Create a server address.
+ ACE_ATM_Addr addr;
+ //if (selector_specified)
+ unsigned char selector = ( argc == 2 ) ? ACE_OS::atoi( argv[ 1 ]) : ACE_ATM_Addr::DEFAULT_SELECTOR;
+ addr.set_selector( selector );
+ ACE_OS::printf( "ATM_Server: selector changed to %d\n", addr.get_selector());
+
+
+ // Create a server, reuse the addr.
+ ACE_ATM_Acceptor peer_acceptor;
+ ACE_ATM_Params params;
+
+ // Not sure why but reuse_addr set to true/1 causes problems for
+ // FORE/XTI/ATM - this is now handled in ACE_ATM_Acceptor::open()
+
+ ACE_HANDLE ret = peer_acceptor.open (addr, 5, params);
+ if ( ret == ACE_INVALID_HANDLE )
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%p\n",
+ "open"),
+ -1);
+
+ ACE_ATM_Stream new_stream;
+ ACE_ATM_Addr local_addr;
+
+ local_addr.set_selector( selector );
+ peer_acceptor.get_local_addr( local_addr );
+
+ ACE_DEBUG ((LM_DEBUG,
+ "starting server at address %s\n",
+ local_addr.addr_to_string ()));
+
+ // Performs the iterative server activities
+ char buf[BUFSIZ];
+ ACE_High_Res_Timer timer;
+ int total;
+ ACE_Time_Value tv;
+ double real_time;
+ double actual_rate;
+
+ for (;;) {
+ // Create a new ACE_ATM_Stream endpoint (note automatic restart
+ // if errno == EINTR).
+ ACE_OS::printf( "ATM_Server: expecting clients\n" );
+
+ if (peer_acceptor.accept (new_stream,
+ &addr,
+ &timeout) == -1) {
+ ACE_ERROR ((LM_ERROR,
+ "%p\n",
+ "accept"));
+ continue;
+ }
+
+ ACE_OS::printf( "ATM_Server: got a connection\n" );
+
+ ACE_UINT16 vpi, vci;
+ vpi = vci = 0;
+ // This has problem on PMP connections on NT
+ //new_stream.get_vpi_vci(vpi, vci);
+ ACE_DEBUG ((LM_DEBUG,
+ "connected to VPI %d VCI %d\n",
+ vpi, vci));
+
+ ACE_OS::printf( "ATM_Server: connection accepted\n" );
+
+ ACE_DEBUG ((LM_DEBUG,
+ "client %s connected\n",
+ addr.addr_to_string ()));
+ ACE_DEBUG ((LM_DEBUG,
+ "client %s connected to host\n",
+ new_stream.get_peer_name ()));
+
+ // Read data from client (terminate on error).
+
+ int recvd = 0;
+
+ for ( ;; ) {
+ total = 0;
+ timer.start_incr();
+
+ for (int r_bytes;
+ (r_bytes = new_stream.recv (buf, sizeof buf, 0)) > 0; ) {
+// ACE_OS::printf( "ATM_Server: received %dB\n", r_bytes );
+
+// if (ACE_OS::write (ACE_STDOUT,
+// buf,
+// r_bytes) != r_bytes)
+// ACE_ERROR ((LM_ERROR,
+// "%p\n",
+// "ACE::send_n"));
+ total += r_bytes;
+
+ if ( total > 10000000 )
+ break;
+
+ }
+
+ timer.stop_incr();
+ timer.elapsed_time_incr( tv );
+ real_time = tv.sec() * ACE_ONE_SECOND_IN_USECS + tv.usec();
+ recvd += total;
+ actual_rate = ( double )recvd * ( double )8 / real_time;
+
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("(%t) bytes = %d, usec = %f, rate = %0.00f Mbps\n"),
+ recvd,
+ real_time,
+ actual_rate < 0 ? 0 : actual_rate ));
+ }
+
+ // Close new endpoint (listening endpoint stays open).
+ if (new_stream.close () == -1)
+ ACE_ERROR ((LM_ERROR,
+ "%p\n",
+ "close"));
+ }
+
+ /* NOTREACHED */
+ return 0;
+}
+#else
+int ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "your platform isn't configured to support ATM\n"),
+ 1);
+}
+#endif /* ACE_HAS_ATM */
diff --git a/ACE/examples/IPC_SAP/ATM_SAP/Makefile.am b/ACE/examples/IPC_SAP/ATM_SAP/Makefile.am
new file mode 100644
index 00000000000..e3ee4011b05
--- /dev/null
+++ b/ACE/examples/IPC_SAP/ATM_SAP/Makefile.am
@@ -0,0 +1,46 @@
+## Process this file with automake to create Makefile.in
+##
+## $Id$
+##
+## This file was generated by MPC. Any changes made directly to
+## this file will be lost the next time it is generated.
+##
+## MPC Command:
+## /acebuilds/ACE_wrappers-repository/bin/mwc.pl -include /acebuilds/MPC/config -include /acebuilds/MPC/templates -feature_file /acebuilds/ACE_wrappers-repository/local.features -noreldefs -type automake -exclude build,Kokyu
+
+ACE_BUILDDIR = $(top_builddir)
+ACE_ROOT = $(top_srcdir)
+
+## Makefile.atm_sap_client.am
+noinst_PROGRAMS = client
+
+client_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+client_SOURCES = \
+ CPP-client.cpp
+
+client_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Makefile.atm_sap_server.am
+noinst_PROGRAMS += server
+
+server_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+server_SOURCES = \
+ CPP-server.cpp
+
+server_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Clean up template repositories, etc.
+clean-local:
+ -rm -f *~ *.bak *.rpo *.sym lib*.*_pure_* core core.*
+ -rm -f gcctemp.c gcctemp so_locations *.ics
+ -rm -rf cxx_repository ptrepository ti_files
+ -rm -rf templateregistry ir.out
+ -rm -rf ptrepository SunWS_cache Templates.DB
diff --git a/ACE/examples/IPC_SAP/ATM_SAP/atm_sap.mpc b/ACE/examples/IPC_SAP/ATM_SAP/atm_sap.mpc
new file mode 100644
index 00000000000..d0f716bb764
--- /dev/null
+++ b/ACE/examples/IPC_SAP/ATM_SAP/atm_sap.mpc
@@ -0,0 +1,16 @@
+// -*- MPC -*-
+// $Id$
+
+project(*client) : aceexe {
+ exename = client
+ Source_Files {
+ CPP-client.cpp
+ }
+}
+
+project(*server) : aceexe {
+ exename = server
+ Source_Files {
+ CPP-server.cpp
+ }
+} \ No newline at end of file
diff --git a/ACE/examples/IPC_SAP/DEV_SAP/Makefile.am b/ACE/examples/IPC_SAP/DEV_SAP/Makefile.am
new file mode 100644
index 00000000000..bb95a489da6
--- /dev/null
+++ b/ACE/examples/IPC_SAP/DEV_SAP/Makefile.am
@@ -0,0 +1,14 @@
+## Process this file with automake to create Makefile.in
+##
+## $Id$
+##
+## This file was generated by MPC. Any changes made directly to
+## this file will be lost the next time it is generated.
+##
+## MPC Command:
+## /acebuilds/ACE_wrappers-repository/bin/mwc.pl -include /acebuilds/MPC/config -include /acebuilds/MPC/templates -feature_file /acebuilds/ACE_wrappers-repository/local.features -noreldefs -type automake -exclude build,Kokyu
+
+SUBDIRS = \
+ reader \
+ writer
+
diff --git a/ACE/examples/IPC_SAP/DEV_SAP/README b/ACE/examples/IPC_SAP/DEV_SAP/README
new file mode 100644
index 00000000000..8e47d8c5cec
--- /dev/null
+++ b/ACE/examples/IPC_SAP/DEV_SAP/README
@@ -0,0 +1,23 @@
+This directory contains a test example for the DEV_SAP
+class category. It implements a class TTY_IO that is
+derived from ACE_DEV_IO and adds a control method
+with specific features for a serial line connection
+(e.g. /dev/ttya and /dev/ttyb on UNIX systems).
+
+The reader/reader executable initializes its
+device-special file (given as command-line parameter),
+reads characters from it (until it recognizes character 'q')
+ands sends the characters read to stdout.
+
+The writer/writer executable also initializes its
+device-special file (given as command-line parameter),
+reads characters from stdin (until'q') and sends them
+to the device.
+
+To run the tests I connect /dev/ttya and /dev/ttyb (with a
+zero modem cable) and start the reader with "reader /dev/ttya"
+and the writer (in a different window) with "writer /dev/ttyb".
+
+Characters typed in the writer window should now appear as output
+in the reader window. Note that characters are buffered till EOL.
+
diff --git a/ACE/examples/IPC_SAP/DEV_SAP/reader/.cvsignore b/ACE/examples/IPC_SAP/DEV_SAP/reader/.cvsignore
new file mode 100644
index 00000000000..a8dd7d50c82
--- /dev/null
+++ b/ACE/examples/IPC_SAP/DEV_SAP/reader/.cvsignore
@@ -0,0 +1,2 @@
+reader
+reader
diff --git a/ACE/examples/IPC_SAP/DEV_SAP/reader/Makefile.am b/ACE/examples/IPC_SAP/DEV_SAP/reader/Makefile.am
new file mode 100644
index 00000000000..bff70f43cd3
--- /dev/null
+++ b/ACE/examples/IPC_SAP/DEV_SAP/reader/Makefile.am
@@ -0,0 +1,38 @@
+## Process this file with automake to create Makefile.in
+##
+## $Id$
+##
+## This file was generated by MPC. Any changes made directly to
+## this file will be lost the next time it is generated.
+##
+## MPC Command:
+## /acebuilds/ACE_wrappers-repository/bin/mwc.pl -include /acebuilds/MPC/config -include /acebuilds/MPC/templates -feature_file /acebuilds/ACE_wrappers-repository/local.features -noreldefs -type automake -exclude build,Kokyu
+
+ACE_BUILDDIR = $(top_builddir)
+ACE_ROOT = $(top_srcdir)
+
+
+## Makefile.dev_sap_reader.am
+
+if !BUILD_ACE_FOR_TAO
+noinst_PROGRAMS = reader
+
+reader_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+reader_SOURCES = \
+ reader.cpp
+
+reader_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+endif !BUILD_ACE_FOR_TAO
+
+## Clean up template repositories, etc.
+clean-local:
+ -rm -f *~ *.bak *.rpo *.sym lib*.*_pure_* core core.*
+ -rm -f gcctemp.c gcctemp so_locations *.ics
+ -rm -rf cxx_repository ptrepository ti_files
+ -rm -rf templateregistry ir.out
+ -rm -rf ptrepository SunWS_cache Templates.DB
diff --git a/ACE/examples/IPC_SAP/DEV_SAP/reader/dev_sap_reader.mpc b/ACE/examples/IPC_SAP/DEV_SAP/reader/dev_sap_reader.mpc
new file mode 100644
index 00000000000..a6535c82e82
--- /dev/null
+++ b/ACE/examples/IPC_SAP/DEV_SAP/reader/dev_sap_reader.mpc
@@ -0,0 +1,11 @@
+// -*- MPC -*-
+// $Id$
+
+project : aceexe {
+ avoids += ace_for_tao
+ exename = reader
+ Source_Files {
+ reader.cpp
+ }
+}
+
diff --git a/ACE/examples/IPC_SAP/DEV_SAP/reader/reader.cpp b/ACE/examples/IPC_SAP/DEV_SAP/reader/reader.cpp
new file mode 100644
index 00000000000..348db5e27e7
--- /dev/null
+++ b/ACE/examples/IPC_SAP/DEV_SAP/reader/reader.cpp
@@ -0,0 +1,69 @@
+// $Id$
+
+#include "ace/DEV_Addr.h"
+#include "ace/DEV_Connector.h"
+#include "ace/TTY_IO.h"
+
+ACE_RCSID(reader, reader, "$Id$")
+
+int ACE_TMAIN (int argc, ACE_TCHAR *argv[])
+{
+ if (argc < 2)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("usage: %s device-filename\n"),
+ argv[0]),
+ 1);
+
+ ACE_TTY_IO read_dev;
+ ACE_DEV_Connector con;
+
+ if (con.connect (read_dev,
+ ACE_DEV_Addr (argv[1])) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ argv[1]),
+ 1);
+
+ ACE_TTY_IO::Serial_Params myparams;
+ myparams.baudrate = 9600;
+ myparams.xonlim = 0;
+ myparams.xofflim = 0;
+ myparams.readmincharacters = 0;
+ myparams.readtimeoutmsec = 10000;
+ myparams.paritymode = "EVEN";
+ myparams.ctsenb = false;
+ myparams.rtsenb = 0;
+ myparams.xinenb = false;
+ myparams.xoutenb = false;
+ myparams.modem = false;
+ myparams.rcvenb = true;
+ myparams.dsrenb = false;
+ myparams.dtrdisable = false;
+ myparams.databits = 8;
+ myparams.stopbits = 1;
+
+ if (read_dev.control (ACE_TTY_IO::SETPARAMS,
+ &myparams) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p control\n"),
+ argv[1]),
+ 1);
+
+ // Read till character 'q'.
+ for (char readback = 'x'; readback != 'q'; )
+ {
+ ssize_t bytes_read =
+ read_dev.recv ((void *) &readback, 1);
+
+ if (bytes_read == 1)
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("read: %c\n"),
+ readback));
+ else if (bytes_read == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p recv\n"),
+ argv[1]), 1);
+ }
+
+ return 0;
+}
diff --git a/ACE/examples/IPC_SAP/DEV_SAP/writer/.cvsignore b/ACE/examples/IPC_SAP/DEV_SAP/writer/.cvsignore
new file mode 100644
index 00000000000..d66df395ab8
--- /dev/null
+++ b/ACE/examples/IPC_SAP/DEV_SAP/writer/.cvsignore
@@ -0,0 +1,2 @@
+writer
+writer
diff --git a/ACE/examples/IPC_SAP/DEV_SAP/writer/Makefile.am b/ACE/examples/IPC_SAP/DEV_SAP/writer/Makefile.am
new file mode 100644
index 00000000000..613a8d08102
--- /dev/null
+++ b/ACE/examples/IPC_SAP/DEV_SAP/writer/Makefile.am
@@ -0,0 +1,38 @@
+## Process this file with automake to create Makefile.in
+##
+## $Id$
+##
+## This file was generated by MPC. Any changes made directly to
+## this file will be lost the next time it is generated.
+##
+## MPC Command:
+## /acebuilds/ACE_wrappers-repository/bin/mwc.pl -include /acebuilds/MPC/config -include /acebuilds/MPC/templates -feature_file /acebuilds/ACE_wrappers-repository/local.features -noreldefs -type automake -exclude build,Kokyu
+
+ACE_BUILDDIR = $(top_builddir)
+ACE_ROOT = $(top_srcdir)
+
+
+## Makefile.dev_sap_writer.am
+
+if !BUILD_ACE_FOR_TAO
+noinst_PROGRAMS = writer
+
+writer_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+writer_SOURCES = \
+ writer.cpp
+
+writer_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+endif !BUILD_ACE_FOR_TAO
+
+## Clean up template repositories, etc.
+clean-local:
+ -rm -f *~ *.bak *.rpo *.sym lib*.*_pure_* core core.*
+ -rm -f gcctemp.c gcctemp so_locations *.ics
+ -rm -rf cxx_repository ptrepository ti_files
+ -rm -rf templateregistry ir.out
+ -rm -rf ptrepository SunWS_cache Templates.DB
diff --git a/ACE/examples/IPC_SAP/DEV_SAP/writer/dev_sap_writer.mpc b/ACE/examples/IPC_SAP/DEV_SAP/writer/dev_sap_writer.mpc
new file mode 100644
index 00000000000..75486584b6d
--- /dev/null
+++ b/ACE/examples/IPC_SAP/DEV_SAP/writer/dev_sap_writer.mpc
@@ -0,0 +1,11 @@
+// -*- MPC -*-
+// $Id$
+
+project : aceexe {
+ avoids += ace_for_tao
+ exename = writer
+ Source_Files {
+ writer.cpp
+ }
+}
+
diff --git a/ACE/examples/IPC_SAP/DEV_SAP/writer/writer.cpp b/ACE/examples/IPC_SAP/DEV_SAP/writer/writer.cpp
new file mode 100644
index 00000000000..44fc262ed61
--- /dev/null
+++ b/ACE/examples/IPC_SAP/DEV_SAP/writer/writer.cpp
@@ -0,0 +1,77 @@
+// $Id$
+
+#include "ace/DEV_Connector.h"
+#include "ace/TTY_IO.h"
+#include "ace/OS_NS_unistd.h"
+
+ACE_RCSID(writer, writer, "$Id$")
+
+int ACE_TMAIN (int argc, ACE_TCHAR *argv[])
+{
+ if (argc < 2)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("usage: %s device-filename\n"),
+ argv[0]), 1);
+
+ ACE_TTY_IO write_dev;
+ ACE_DEV_Connector con;
+
+ if (con.connect (write_dev,
+ ACE_DEV_Addr (argv[1])) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ argv[1]),
+ 1);
+
+ ACE_TTY_IO::Serial_Params myparams;
+ myparams.baudrate = 9600;
+ myparams.xonlim = 0;
+ myparams.xofflim = 0;
+ myparams.readmincharacters = 0;
+ myparams.readtimeoutmsec = 10000;
+ myparams.paritymode = "EVEN";
+ myparams.ctsenb = false;
+ myparams.rtsenb = 0;
+ myparams.xinenb = false;
+ myparams.xoutenb = false;
+ myparams.modem = false;
+ myparams.rcvenb = true;
+ myparams.dsrenb = false;
+ myparams.dtrdisable = false;
+ myparams.databits = 8;
+ myparams.stopbits = 1;
+
+ if (write_dev.control (ACE_TTY_IO::SETPARAMS,
+ &myparams) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("control")),
+ 1);
+
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("enter character to send, q terminates :\n")));
+
+ for (char writeto;
+ ACE_OS::read (ACE_STDIN, &writeto, 1) != -1;
+ )
+ {
+ ssize_t bytes_written =
+ write_dev.send_n ((void *) &writeto,
+ 1);
+
+ if (bytes_written != 1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("send")),
+ 1);
+ if (writeto == 'q')
+ break;
+ }
+
+ if (write_dev.close () == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("close")),
+ 1);
+ return 0;
+}
diff --git a/ACE/examples/IPC_SAP/FIFO_SAP/.cvsignore b/ACE/examples/IPC_SAP/FIFO_SAP/.cvsignore
new file mode 100644
index 00000000000..5d0734ead63
--- /dev/null
+++ b/ACE/examples/IPC_SAP/FIFO_SAP/.cvsignore
@@ -0,0 +1,10 @@
+FIFO-Msg-client
+FIFO-Msg-client
+FIFO-Msg-server
+FIFO-Msg-server
+FIFO-client
+FIFO-client
+FIFO-server
+FIFO-server
+FIFO-test
+FIFO-test
diff --git a/ACE/examples/IPC_SAP/FIFO_SAP/FIFO-Msg-client.cpp b/ACE/examples/IPC_SAP/FIFO_SAP/FIFO-Msg-client.cpp
new file mode 100644
index 00000000000..3f267ba66ce
--- /dev/null
+++ b/ACE/examples/IPC_SAP/FIFO_SAP/FIFO-Msg-client.cpp
@@ -0,0 +1,43 @@
+// $Id$
+
+#include "ace/FIFO_Send_Msg.h"
+#include "ace/OS_NS_stdio.h"
+#include "ace/OS_main.h"
+#include "ace/OS_NS_stdlib.h"
+#include "ace/OS_NS_time.h"
+#include "ace/OS_NS_string.h"
+
+ACE_RCSID(FIFO_SAP, FIFO_Msg_client, "$Id$")
+
+#if defined (ACE_HAS_STREAM_PIPES)
+
+int
+ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ ACE_FIFO_Send_Msg client (ACE_DEFAULT_RENDEZVOUS);
+
+ char buf[BUFSIZ];
+ ACE_Str_Buf msg (buf);
+
+ ACE_OS::srand (unsigned (ACE_OS::time (0)));
+
+ while (ACE_OS::fgets (buf, sizeof buf, stdin) != 0)
+ {
+ msg.len = ACE_OS::strlen (buf) + 1;
+ if (client.send (ACE_OS::rand () % 11, &msg) == -1)
+ ::perror ("send");
+ }
+
+ if (client.close () == -1)
+ ACE_OS::perror ("close"), ACE_OS::exit (1);
+
+ return 0;
+}
+#else
+#include "ace/os_include/os_stdio.h"
+int ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ ACE_OS::fprintf (stderr, "This feature is not supported\n");
+ return 0;
+}
+#endif /* ACE_HAS_STREAM_PIPES */
diff --git a/ACE/examples/IPC_SAP/FIFO_SAP/FIFO-Msg-server.cpp b/ACE/examples/IPC_SAP/FIFO_SAP/FIFO-Msg-server.cpp
new file mode 100644
index 00000000000..fc96ec71dbb
--- /dev/null
+++ b/ACE/examples/IPC_SAP/FIFO_SAP/FIFO-Msg-server.cpp
@@ -0,0 +1,49 @@
+// $Id$
+
+#include "ace/FIFO_Recv_Msg.h"
+#include "ace/Log_Msg.h"
+#include "ace/OS_NS_stdio.h"
+#include "ace/OS_NS_unistd.h"
+#include "ace/OS_NS_stdlib.h"
+#include "ace/OS_NS_stropts.h"
+#include "ace/OS_main.h"
+
+ACE_RCSID(FIFO_SAP, FIFO_Msg_server, "$Id$")
+
+#if defined (ACE_HAS_STREAM_PIPES)
+
+int
+ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ ACE_OS::unlink (ACE_DEFAULT_RENDEZVOUS);
+ ACE_FIFO_Recv_Msg server (ACE_DEFAULT_RENDEZVOUS);
+ char buf[BUFSIZ];
+ ACE_Str_Buf msg (buf, 0, sizeof buf);
+ int flags = MSG_ANY;
+ int band = 0;
+ int n;
+
+ while ((n = server.recv (&band, &msg, (ACE_Str_Buf *) 0, &flags)) >= 0)
+ {
+ if (msg.len == 0)
+ break;
+ else
+ ACE_DEBUG ((LM_DEBUG, "%4d (%4d): %*s",
+ msg.len, band, msg.len, msg.buf));
+ flags = MSG_ANY;
+ band = 0;
+ }
+
+ if (n == -1)
+ ACE_OS::perror ("recv"), ACE_OS::exit (1);
+
+ return 0;
+}
+#else
+int ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ ACE_ERROR ((LM_INFO,
+ ACE_TEXT ("This feature is not supported\n")));
+ return 0;
+}
+#endif /* ACE_HAS_STREAM_PIPES */
diff --git a/ACE/examples/IPC_SAP/FIFO_SAP/FIFO-client.cpp b/ACE/examples/IPC_SAP/FIFO_SAP/FIFO-client.cpp
new file mode 100644
index 00000000000..8c80809f380
--- /dev/null
+++ b/ACE/examples/IPC_SAP/FIFO_SAP/FIFO-client.cpp
@@ -0,0 +1,29 @@
+// $Id$
+
+#include "ace/FIFO_Send.h"
+#include "ace/Log_Msg.h"
+#include "ace/OS_NS_string.h"
+#include "ace/OS_NS_stdio.h"
+#include "ace/OS_main.h"
+
+ACE_RCSID(FIFO_SAP, FIFO_client, "$Id$")
+
+int
+ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ ACE_FIFO_Send client (ACE_DEFAULT_RENDEZVOUS);
+ ACE_TCHAR buf[BUFSIZ];
+
+ while (ACE_OS::fgets (buf, sizeof buf, stdin) != 0)
+ {
+ ssize_t n = ACE_OS::strlen (buf);
+
+ if (client.send (buf, n) != n)
+ ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "send"), 1);
+ }
+
+ if (client.close () == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "close"), 1);
+
+ return 0;
+}
diff --git a/ACE/examples/IPC_SAP/FIFO_SAP/FIFO-server.cpp b/ACE/examples/IPC_SAP/FIFO_SAP/FIFO-server.cpp
new file mode 100644
index 00000000000..4cd32c03449
--- /dev/null
+++ b/ACE/examples/IPC_SAP/FIFO_SAP/FIFO-server.cpp
@@ -0,0 +1,30 @@
+// $Id$
+
+#include "ace/FIFO_Recv.h"
+#include "ace/Log_Msg.h"
+#include "ace/OS_NS_stdio.h"
+#include "ace/OS_NS_unistd.h"
+#include "ace/OS_main.h"
+
+ACE_RCSID(FIFO_SAP, FIFO_server, "$Id$")
+
+int
+ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ ACE_OS::unlink (ACE_DEFAULT_RENDEZVOUS);
+ ACE_FIFO_Recv server (ACE_DEFAULT_RENDEZVOUS);
+ char buf[BUFSIZ];
+ int n;
+
+ while ((n = server.recv (buf, sizeof buf)) > 0)
+ {
+ ACE_OS::printf ("%4d: ", n);
+ ACE_OS::fflush (stdout);
+ ACE_OS::write (ACE_STDOUT, buf, n);
+ }
+
+ if (n == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "recv"), 1);
+
+ return 0;
+}
diff --git a/ACE/examples/IPC_SAP/FIFO_SAP/FIFO-test.cpp b/ACE/examples/IPC_SAP/FIFO_SAP/FIFO-test.cpp
new file mode 100644
index 00000000000..d6911908658
--- /dev/null
+++ b/ACE/examples/IPC_SAP/FIFO_SAP/FIFO-test.cpp
@@ -0,0 +1,122 @@
+// $Id$
+
+// Purpose: This program uses ACE_FIFO wrappers to perform
+// interprocess communication between a parent process and a child
+// process. The parents reads from an input file and writes it into
+// the fifo. The child reads from the ACE_FIFO and executes the more
+// command.
+
+#include "ace/FIFO_Recv.h"
+#include "ace/FIFO_Send.h"
+#include "ace/Log_Msg.h"
+#include "ace/OS_NS_sys_wait.h"
+#include "ace/OS_NS_unistd.h"
+#include "ace/OS_NS_stdlib.h"
+#include "ace/OS_NS_fcntl.h"
+
+ACE_RCSID(FIFO_SAP, FIFO_test, "$Id$")
+
+#define PERMS 0666
+#define EXEC_NAME "more"
+#define EXEC_COMMAND_ARG "more"
+
+static const ACE_TCHAR *FIFO_NAME = ACE_TEXT ("/tmp/fifo");
+
+static int
+do_child (ACE_FIFO_Recv &fifo_reader)
+{
+ // Set child's stdin to read from the fifo.
+ if (ACE_OS::close (ACE_STDIN) == -1
+ || ACE_OS::dup (fifo_reader.get_handle ()) == ACE_INVALID_HANDLE)
+ return -1;
+
+ char *argv[2];
+ argv[0] = const_cast<char *> (EXEC_COMMAND_ARG);
+ argv[1] = 0;
+
+ if (ACE_OS::execvp (EXEC_NAME, argv) == -1)
+ return -1;
+ return 0;
+}
+
+static int
+do_parent (const ACE_TCHAR fifo_name[],
+ ACE_TCHAR input_filename[])
+{
+ ACE_FIFO_Send fifo_sender (fifo_name, O_WRONLY | O_CREAT);
+ ssize_t len;
+ char buf[BUFSIZ];
+
+ if (fifo_sender.get_handle () == ACE_INVALID_HANDLE)
+ return -1;
+
+ ACE_HANDLE inputfd =
+ ACE_OS::open (input_filename, O_RDONLY);
+
+ if (inputfd == ACE_INVALID_HANDLE)
+ return -1;
+
+ // Read from input file and write into input end of the fifo.
+
+ while ((len = ACE_OS::read (inputfd, buf, sizeof buf)) > 0)
+ if (fifo_sender.send (buf, len) != len)
+ return -1;
+
+ if (len == -1)
+ return -1;
+
+ if (fifo_sender.remove () == -1)
+ return -1;
+ return 0;
+}
+
+int
+ACE_TMAIN (int argc, ACE_TCHAR *argv[])
+{
+ ACE_LOG_MSG->open (argv[0]);
+
+ if (argc != 2)
+ {
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("usage: %n input-file\n"),
+ 1));
+ ACE_OS::exit (1);
+ }
+
+ ACE_FIFO_Recv fifo_reader (FIFO_NAME, O_RDONLY | O_CREAT, PERMS, 0);
+
+ if (fifo_reader.get_handle () == ACE_INVALID_HANDLE)
+ return -1;
+
+ pid_t child_pid = ACE_OS::fork ();
+
+ switch (child_pid)
+ {
+ case -1:
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("%n: %p\n%a"),
+ ACE_TEXT ("fork"),
+ 1));
+ case 0:
+ if (do_child (fifo_reader) == -1)
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("%n: %p\n%a"),
+ ACE_TEXT ("do_child"),
+ 1));
+ default:
+ if (do_parent (FIFO_NAME, argv[1]) == -1)
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("%n: %p\n%a"),
+ ACE_TEXT ("do_parent"),
+ 1));
+
+ // wait for child to ACE_OS::exit.
+ if (ACE_OS::waitpid (child_pid, (ACE_exitcode *) 0, 0) == -1)
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("%n: %p\n%a"),
+ ACE_TEXT ("waitpid"),
+ 1));
+ }
+
+ return 0;
+}
diff --git a/ACE/examples/IPC_SAP/FIFO_SAP/Makefile.am b/ACE/examples/IPC_SAP/FIFO_SAP/Makefile.am
new file mode 100644
index 00000000000..9a9cba4b837
--- /dev/null
+++ b/ACE/examples/IPC_SAP/FIFO_SAP/Makefile.am
@@ -0,0 +1,98 @@
+## Process this file with automake to create Makefile.in
+##
+## $Id$
+##
+## This file was generated by MPC. Any changes made directly to
+## this file will be lost the next time it is generated.
+##
+## MPC Command:
+## /acebuilds/ACE_wrappers-repository/bin/mwc.pl -include /acebuilds/MPC/config -include /acebuilds/MPC/templates -feature_file /acebuilds/ACE_wrappers-repository/local.features -noreldefs -type automake -exclude build,Kokyu
+
+ACE_BUILDDIR = $(top_builddir)
+ACE_ROOT = $(top_srcdir)
+
+
+## Makefile.Fifo_Sap_Msg_Client.am
+noinst_PROGRAMS = FIFO-Msg-client
+
+FIFO_Msg_client_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+FIFO_Msg_client_SOURCES = \
+ FIFO-Msg-client.cpp
+
+FIFO_Msg_client_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Makefile.Fifo_Sap_Msg_Server.am
+noinst_PROGRAMS += FIFO-Msg-server
+
+FIFO_Msg_server_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+FIFO_Msg_server_SOURCES = \
+ FIFO-Msg-server.cpp
+
+FIFO_Msg_server_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Makefile.fifo_sap_client.am
+
+if !BUILD_ACE_FOR_TAO
+noinst_PROGRAMS += FIFO-client
+
+FIFO_client_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+FIFO_client_SOURCES = \
+ FIFO-client.cpp
+
+FIFO_client_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+endif !BUILD_ACE_FOR_TAO
+
+## Makefile.fifo_sap_server.am
+
+if !BUILD_ACE_FOR_TAO
+noinst_PROGRAMS += FIFO-server
+
+FIFO_server_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+FIFO_server_SOURCES = \
+ FIFO-server.cpp
+
+FIFO_server_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+endif !BUILD_ACE_FOR_TAO
+
+## Makefile.fifo_sap_test.am
+
+if !BUILD_ACE_FOR_TAO
+noinst_PROGRAMS += FIFO-test
+
+FIFO_test_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+FIFO_test_SOURCES = \
+ FIFO-test.cpp
+
+FIFO_test_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+endif !BUILD_ACE_FOR_TAO
+
+## Clean up template repositories, etc.
+clean-local:
+ -rm -f *~ *.bak *.rpo *.sym lib*.*_pure_* core core.*
+ -rm -f gcctemp.c gcctemp so_locations *.ics
+ -rm -rf cxx_repository ptrepository ti_files
+ -rm -rf templateregistry ir.out
+ -rm -rf ptrepository SunWS_cache Templates.DB
diff --git a/ACE/examples/IPC_SAP/FIFO_SAP/fifo_sap.mpc b/ACE/examples/IPC_SAP/FIFO_SAP/fifo_sap.mpc
new file mode 100644
index 00000000000..1e6d04447e5
--- /dev/null
+++ b/ACE/examples/IPC_SAP/FIFO_SAP/fifo_sap.mpc
@@ -0,0 +1,42 @@
+// -*- MPC -*-
+// $Id$
+
+project(*client) : aceexe {
+ avoids += ace_for_tao
+ exename = FIFO-client
+ Source_Files {
+ FIFO-client.cpp
+ }
+}
+
+project(*server) : aceexe {
+ avoids += ace_for_tao
+ exename = FIFO-server
+ Source_Files {
+ FIFO-server.cpp
+ }
+}
+
+project(*Msg_Client) : aceexe {
+ exename = FIFO-Msg-client
+ Source_Files {
+ FIFO-Msg-client.cpp
+ }
+}
+
+project(*Msg_Server) : aceexe {
+ exename = FIFO-Msg-server
+ Source_Files {
+ FIFO-Msg-server.cpp
+ }
+}
+
+project(*test) : aceexe {
+ avoids += ace_for_tao
+ exename = FIFO-test
+ Source_Files {
+ FIFO-test.cpp
+ }
+}
+
+
diff --git a/ACE/examples/IPC_SAP/FILE_SAP/.cvsignore b/ACE/examples/IPC_SAP/FILE_SAP/.cvsignore
new file mode 100644
index 00000000000..db648aa002d
--- /dev/null
+++ b/ACE/examples/IPC_SAP/FILE_SAP/.cvsignore
@@ -0,0 +1,2 @@
+client
+client
diff --git a/ACE/examples/IPC_SAP/FILE_SAP/Makefile.am b/ACE/examples/IPC_SAP/FILE_SAP/Makefile.am
new file mode 100644
index 00000000000..e39aa964edf
--- /dev/null
+++ b/ACE/examples/IPC_SAP/FILE_SAP/Makefile.am
@@ -0,0 +1,38 @@
+## Process this file with automake to create Makefile.in
+##
+## $Id$
+##
+## This file was generated by MPC. Any changes made directly to
+## this file will be lost the next time it is generated.
+##
+## MPC Command:
+## /acebuilds/ACE_wrappers-repository/bin/mwc.pl -include /acebuilds/MPC/config -include /acebuilds/MPC/templates -feature_file /acebuilds/ACE_wrappers-repository/local.features -noreldefs -type automake -exclude build,Kokyu
+
+ACE_BUILDDIR = $(top_builddir)
+ACE_ROOT = $(top_srcdir)
+
+
+## Makefile.file_sap_client.am
+
+if !BUILD_ACE_FOR_TAO
+noinst_PROGRAMS = client
+
+client_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+client_SOURCES = \
+ client.cpp
+
+client_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+endif !BUILD_ACE_FOR_TAO
+
+## Clean up template repositories, etc.
+clean-local:
+ -rm -f *~ *.bak *.rpo *.sym lib*.*_pure_* core core.*
+ -rm -f gcctemp.c gcctemp so_locations *.ics
+ -rm -rf cxx_repository ptrepository ti_files
+ -rm -rf templateregistry ir.out
+ -rm -rf ptrepository SunWS_cache Templates.DB
diff --git a/ACE/examples/IPC_SAP/FILE_SAP/client.cpp b/ACE/examples/IPC_SAP/FILE_SAP/client.cpp
new file mode 100644
index 00000000000..f26302f3b57
--- /dev/null
+++ b/ACE/examples/IPC_SAP/FILE_SAP/client.cpp
@@ -0,0 +1,90 @@
+// $Id$
+
+#include "ace/OS_main.h"
+#include "ace/FILE_Addr.h"
+#include "ace/FILE_Connector.h"
+#include "ace/FILE_IO.h"
+#include "ace/OS_NS_string.h"
+#include "ace/OS_NS_stdio.h"
+
+ACE_RCSID(FILE_SAP, client, "$Id$")
+
+int
+ACE_TMAIN (int argc, ACE_TCHAR *argv[])
+{
+ if (argc < 3 || argc > 3)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "usage: %s filename string\n",
+ argv[0]),
+ 1);
+
+ ACE_TCHAR *readback = new ACE_TCHAR[ACE_OS::strlen (argv[1]) + 1];
+
+ ACE_FILE_Info fileinfo;
+ ACE_FILE_IO cli_file;
+ ACE_FILE_Connector con;
+
+ if (con.connect (cli_file,
+ ACE_FILE_Addr (argv[1]),
+ 0,
+ ACE_Addr::sap_any, 0,
+ O_RDWR|O_APPEND|O_CREAT,
+ ACE_DEFAULT_FILE_PERMS) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%p\n to %s",
+ "connect",
+ argv[1]),
+ -1);
+
+ ssize_t len = ACE_OS::strlen (argv[2]) + 1;
+
+ if (cli_file.send (argv[2], len) != len)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%p\n",
+ "send"),
+ 1);
+
+ if (cli_file.get_info (&fileinfo) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%p\n",
+ "get_info"),
+ 1);
+ else
+ ACE_OS::printf ("fileinfo : mode = %o\nno of links = %lu\nsize = %lu\n",
+ (u_int) fileinfo.mode_ & 0777,
+ static_cast<u_long > (fileinfo.nlink_),
+ (u_long) fileinfo.size_);
+
+ off_t fpos = cli_file.tell ();
+
+ if (fpos == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%p\n",
+ "tell"),
+ 1);
+ else
+ ACE_OS::printf ("current filepointer is at %ld\n",
+ (long int) fpos);
+
+ if (cli_file.seek (0,
+ SEEK_SET) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%p\n",
+ "seek"),
+ 1);
+ if (cli_file.recv (readback, len) != len)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%p\n",
+ "recv"),
+ 1);
+
+ ACE_OS::printf ("read back :%s\n",
+ readback);
+
+ if (cli_file.close () == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%p\n",
+ "close"),
+ 1);
+ return 0;
+}
diff --git a/ACE/examples/IPC_SAP/FILE_SAP/file_sap_client.mpc b/ACE/examples/IPC_SAP/FILE_SAP/file_sap_client.mpc
new file mode 100644
index 00000000000..24f9a2b3a61
--- /dev/null
+++ b/ACE/examples/IPC_SAP/FILE_SAP/file_sap_client.mpc
@@ -0,0 +1,11 @@
+// -*- MPC -*-
+// $Id$
+
+project : aceexe {
+ avoids += ace_for_tao
+ exename = client
+ Source_Files {
+ client.cpp
+ }
+}
+
diff --git a/ACE/examples/IPC_SAP/FILE_SAP/testfile b/ACE/examples/IPC_SAP/FILE_SAP/testfile
new file mode 100644
index 00000000000..e7cbb71a0d5
--- /dev/null
+++ b/ACE/examples/IPC_SAP/FILE_SAP/testfile
@@ -0,0 +1 @@
+testfile \ No newline at end of file
diff --git a/ACE/examples/IPC_SAP/Makefile.am b/ACE/examples/IPC_SAP/Makefile.am
new file mode 100644
index 00000000000..87f2a00844b
--- /dev/null
+++ b/ACE/examples/IPC_SAP/Makefile.am
@@ -0,0 +1,21 @@
+## Process this file with automake to create Makefile.in
+##
+## $Id$
+##
+## This file was generated by MPC. Any changes made directly to
+## this file will be lost the next time it is generated.
+##
+## MPC Command:
+## /acebuilds/ACE_wrappers-repository/bin/mwc.pl -include /acebuilds/MPC/config -include /acebuilds/MPC/templates -feature_file /acebuilds/ACE_wrappers-repository/local.features -noreldefs -type automake -exclude build,Kokyu
+
+SUBDIRS = \
+ ATM_SAP \
+ DEV_SAP \
+ FIFO_SAP \
+ FILE_SAP \
+ SOCK_SAP \
+ SPIPE_SAP \
+ SSL_SAP \
+ TLI_SAP \
+ UPIPE_SAP
+
diff --git a/ACE/examples/IPC_SAP/SOCK_SAP/.cvsignore b/ACE/examples/IPC_SAP/SOCK_SAP/.cvsignore
new file mode 100644
index 00000000000..07a07ab2d27
--- /dev/null
+++ b/ACE/examples/IPC_SAP/SOCK_SAP/.cvsignore
@@ -0,0 +1,18 @@
+C-inclient
+C-inclient
+C-inserver
+C-inserver
+CPP-inclient
+CPP-inclient
+CPP-inserver
+CPP-inserver
+CPP-memclient
+CPP-memclient
+CPP-memserver
+CPP-memserver
+CPP-unclient
+CPP-unclient
+CPP-unserver
+CPP-unserver
+FD-unclient
+FD-unclient
diff --git a/ACE/examples/IPC_SAP/SOCK_SAP/C-inclient.cpp b/ACE/examples/IPC_SAP/SOCK_SAP/C-inclient.cpp
new file mode 100644
index 00000000000..e4cf8997857
--- /dev/null
+++ b/ACE/examples/IPC_SAP/SOCK_SAP/C-inclient.cpp
@@ -0,0 +1,84 @@
+// $Id$
+
+#include "ace/OS_main.h"
+#include "ace/OS_NS_string.h"
+#include "ace/OS_NS_sys_socket.h"
+#include "ace/OS_NS_unistd.h"
+#include "ace/OS_NS_stdlib.h"
+#include "ace/OS_NS_stdio.h"
+#include "ace/OS_NS_netdb.h"
+#include "ace/Default_Constants.h"
+
+ACE_RCSID(SOCK_SAP, C_inclient, "$Id$")
+
+/* BSD socket client */
+
+int
+ACE_TMAIN (int argc, ACE_TCHAR *argv[])
+{
+ // Initialize WinSock DLL on Win32...
+ ACE_OS::socket_init (ACE_WSOCK_VERSION);
+
+ struct sockaddr_in saddr;
+ struct hostent *hp;
+ const ACE_TCHAR *host = argc > 1 ? argv[1] : ACE_DEFAULT_SERVER_HOST;
+ u_short port_num =
+ htons (argc > 2 ? ACE_OS::atoi (argv[2]) : ACE_DEFAULT_SERVER_PORT);
+ int sockbufsize = argc > 3 ? ACE_OS::atoi (argv[3]) : 0;
+ char buf[BUFSIZ];
+ ACE_HANDLE s_handle;
+ int w_bytes;
+ int r_bytes;
+ int n;
+
+ // Create a local endpoint of communication.
+ if ((s_handle = ACE_OS::socket (PF_INET, SOCK_STREAM, 0)) == ACE_INVALID_HANDLE)
+ ACE_OS::perror (ACE_TEXT("socket")), ACE_OS::exit (1);
+
+ // If a sockbufsize was specified, set it for both send and receive.
+ if (sockbufsize > 0)
+ {
+ if (ACE_OS::setsockopt (s_handle, SOL_SOCKET, SO_SNDBUF,
+ (const char *) &sockbufsize,
+ sizeof (sockbufsize)) != 0)
+ ACE_OS::perror (ACE_TEXT("SO_SNDBUF")), ACE_OS::exit (1);
+ if (ACE_OS::setsockopt (s_handle, SOL_SOCKET, SO_RCVBUF,
+ (const char *) &sockbufsize,
+ sizeof (sockbufsize)) != 0)
+ ACE_OS::perror (ACE_TEXT("SO_RCVBUF")), ACE_OS::exit (1);
+ }
+
+ // Determine IP address of the server.
+ if ((hp = ACE_OS::gethostbyname (ACE_TEXT_ALWAYS_CHAR(host))) == 0)
+ ACE_OS::perror (ACE_TEXT("gethostbyname")), ACE_OS::exit (1);
+
+ // Set up the address information to contact the server.
+ ACE_OS::memset ((void *) &saddr, 0, sizeof saddr);
+ saddr.sin_family = AF_INET;
+ saddr.sin_port = port_num;
+ ACE_OS::memcpy (&saddr.sin_addr, hp->h_addr, hp->h_length);
+
+ // Establish connection with remote server.
+ if (ACE_OS::connect (s_handle,
+ reinterpret_cast<sockaddr *> (&saddr),
+ sizeof saddr) == -1)
+ ACE_OS::perror (ACE_TEXT("connect")), ACE_OS::exit (1);
+
+ // Send data to server (correctly handles "incomplete writes" due to
+ // flow control).
+
+ while ((r_bytes = ACE_OS::read (ACE_STDIN, buf, sizeof buf)) > 0)
+ for (w_bytes = 0; w_bytes < r_bytes; w_bytes += n)
+ if ((n = ACE_OS::send (s_handle, buf + w_bytes,
+ r_bytes - w_bytes)) < 0)
+ ACE_OS::perror (ACE_TEXT("write")), ACE_OS::exit (1);
+
+ if (ACE_OS::recv (s_handle, buf, 1) == 1)
+ ACE_OS::write (ACE_STDOUT, buf, 1);
+
+ // Explicitly close the connection.
+ if (ACE_OS::closesocket (s_handle) == -1)
+ ACE_OS::perror (ACE_TEXT("close")), ACE_OS::exit (1);
+
+ return 0;
+}
diff --git a/ACE/examples/IPC_SAP/SOCK_SAP/C-inserver.cpp b/ACE/examples/IPC_SAP/SOCK_SAP/C-inserver.cpp
new file mode 100644
index 00000000000..0a6915cc463
--- /dev/null
+++ b/ACE/examples/IPC_SAP/SOCK_SAP/C-inserver.cpp
@@ -0,0 +1,116 @@
+// $Id$
+
+#include "ace/OS_main.h"
+#include "ace/OS_NS_string.h"
+#include "ace/OS_NS_sys_socket.h"
+#include "ace/OS_NS_unistd.h"
+#include "ace/OS_NS_stdlib.h"
+#include "ace/OS_NS_stdio.h"
+#include "ace/OS_NS_netdb.h"
+#include "ace/OS_NS_errno.h"
+#include "ace/Default_Constants.h"
+
+ACE_RCSID(SOCK_SAP, C_inserver, "$Id$")
+
+/* BSD socket server. */
+
+int ACE_TMAIN (int argc, ACE_TCHAR *argv[])
+{
+ // Initialize WinSock DLL on Win32...
+ ACE_OS::socket_init (ACE_WSOCK_VERSION);
+
+ u_short port_num =
+ htons (argc > 1 ? ACE_OS::atoi (argv[1]) : ACE_DEFAULT_SERVER_PORT);
+ int sockbufsize = argc > 2 ? ACE_OS::atoi (argv[2]) : 0;
+ struct sockaddr_in saddr;
+ ACE_HANDLE s_handle, n_handle;
+
+ /* Create a local endpoint of communication */
+ if ((s_handle = ACE_OS::socket (PF_INET, SOCK_STREAM, 0)) == ACE_INVALID_HANDLE)
+ ACE_OS::perror (ACE_TEXT("socket")), ACE_OS::exit (1);
+
+ // If a sockbufsize was specified, set it for both send and receive.
+ if (sockbufsize > 0)
+ {
+ if (ACE_OS::setsockopt (s_handle, SOL_SOCKET, SO_SNDBUF,
+ (const char *) &sockbufsize,
+ sizeof (sockbufsize)) != 0)
+ ACE_OS::perror (ACE_TEXT("SO_SNDBUF")), ACE_OS::exit (1);
+ if (ACE_OS::setsockopt (s_handle, SOL_SOCKET, SO_RCVBUF,
+ (const char *) &sockbufsize,
+ sizeof (sockbufsize)) != 0)
+ ACE_OS::perror (ACE_TEXT("SO_RCVBUF")), ACE_OS::exit (1);
+ }
+
+ /* Set up the address information to become a server */
+ ACE_OS::memset ((void *) &saddr, 0, sizeof saddr);
+ saddr.sin_family = AF_INET;
+ saddr.sin_port = port_num;
+ saddr.sin_addr.s_addr = INADDR_ANY;
+
+ /* Associate address with endpoint */
+ if (ACE_OS::bind (s_handle,
+ reinterpret_cast<struct sockaddr *> (&saddr),
+ sizeof saddr) == -1)
+ ACE_OS::perror (ACE_TEXT("bind")), ACE_OS::exit (1);
+
+ /* Make endpoint listen for service requests */
+ if (ACE_OS::listen (s_handle, 5) == -1)
+ ACE_OS::perror (ACE_TEXT("listen")), ACE_OS::exit (1);
+
+ /* Performs the iterative server activities */
+
+ for (;;)
+ {
+ char buf[BUFSIZ];
+ int r_bytes;
+ struct sockaddr_in cli_addr;
+ int cli_addr_len = sizeof cli_addr;
+ struct hostent *hp;
+
+ /* Create a new endpoint of communication */
+ do
+ n_handle =
+ ACE_OS::accept (s_handle,
+ reinterpret_cast<struct sockaddr *> (&cli_addr),
+ &cli_addr_len);
+ while (n_handle == ACE_INVALID_HANDLE && errno == EINTR);
+
+ if (n_handle == ACE_INVALID_HANDLE)
+ {
+ ACE_OS::perror (ACE_TEXT("accept"));
+ continue;
+ }
+
+#if !defined(_UNICOS)
+ int addr_len = sizeof cli_addr.sin_addr.s_addr;
+#else /* ! _UNICOS */
+ // sizeof on bitfield fails
+ int addr_len = sizeof cli_addr.sin_addr; // 32 bit biffield in UNICOS
+#endif /* ! _UNICOS */
+ hp = ACE_OS::gethostbyaddr ((char *) &cli_addr.sin_addr,
+ addr_len, AF_INET);
+
+ if (hp != 0)
+ ACE_OS::printf ("client %s\n", hp->h_name), ACE_OS::fflush (stdout);
+ else
+ ACE_OS::perror (ACE_TEXT("gethostbyaddr"));
+
+ /* Read data from client (terminate on error) */
+
+ while ((r_bytes = ACE_OS::recv (n_handle, buf, sizeof buf)) > 0)
+ if (ACE_OS::write (ACE_STDOUT, buf, r_bytes) != r_bytes)
+ ACE_OS::perror (ACE_TEXT("write")), ACE_OS::exit (1);
+
+ if (ACE_OS::send (n_handle, "", 1) != 1)
+ ::perror ("write"), ACE_OS::exit (1);
+
+ /* Close the new endpoint
+ (listening endpoint remains open) */
+ if (ACE_OS::closesocket (n_handle) == -1)
+ ACE_OS::perror (ACE_TEXT("close")), ACE_OS::exit (1);
+ ACE_OS::exit (0);
+ }
+
+ ACE_NOTREACHED (return 0;)
+}
diff --git a/ACE/examples/IPC_SAP/SOCK_SAP/CPP-inclient.cpp b/ACE/examples/IPC_SAP/SOCK_SAP/CPP-inclient.cpp
new file mode 100644
index 00000000000..3428b02cd12
--- /dev/null
+++ b/ACE/examples/IPC_SAP/SOCK_SAP/CPP-inclient.cpp
@@ -0,0 +1,424 @@
+// $Id$
+
+// This tests the features of the <ACE_SOCK_Connector> and
+// <ACE_SOCK_Stream> classes. In addition, it can be used to test the
+// oneway and twoway latency and throughput at the socket-level. This
+// is useful as a baseline to compare against ORB-level performance
+// for the same types of data.
+
+#include "CPP-inclient.h"
+
+#include "ace/SOCK_Connector.h"
+#include "ace/INET_Addr.h"
+#include "ace/Thread_Manager.h"
+#include "ace/Singleton.h"
+#include "ace/Get_Opt.h"
+#include "ace/High_Res_Timer.h"
+#include "ace/OS_NS_string.h"
+#include "ace/OS_NS_unistd.h"
+#include "ace/OS_main.h"
+
+ACE_RCSID(SOCK_SAP, CPP_inclient, "$Id$")
+
+Options::Options (void)
+ : host_ (ACE_DEFAULT_SERVER_HOST),
+ port_ (ACE_DEFAULT_SERVER_PORT),
+ sleep_time_ (0, 0), // By default, don't sleep between calls.
+ threads_ (10),
+ quit_string_ (ACE_TEXT("q")),
+ message_len_ (0),
+ message_buf_ (0),
+ io_source_ (ACE_INVALID_HANDLE), // Defaults to using the generator.
+ iterations_ (10000),
+ oneway_ (1) // Make oneway calls the default.
+#if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0)
+ , barrier_ (0)
+#endif /* ACE_MT_SAFE */
+{
+}
+
+Options::~Options (void)
+{
+ ACE_MT (delete this->barrier_);
+ delete [] this->message_buf_;
+}
+
+// Options Singleton.
+typedef ACE_Singleton<Options, ACE_SYNCH_RECURSIVE_MUTEX> OPTIONS;
+
+int
+Options::init (void)
+{
+
+ ACE_DEBUG((LM_DEBUG,"Options::init, len = %d\n",this->message_len_));
+
+ // Check for default case.
+ if (this->message_len_ == 0)
+ this->message_len_ = ACE_OS::strlen ("TAO");
+ ACE_DEBUG((LM_DEBUG,"Options::init, len = %d\n",this->message_len_));
+
+ this->message_len_ += sizeof (ACE_UINT32);
+ ACE_DEBUG((LM_DEBUG,"Options::init, len = %d\n",this->message_len_));
+
+ ACE_NEW_RETURN (this->message_buf_,
+ char[this->message_len_],
+ -1);
+
+ // Copy the length into the beginning of the message.
+ ACE_UINT32 length = ntohl (this->message_len_);
+ ACE_OS::memcpy ((void *) this->message_buf_,
+ (void *) &length,
+ sizeof length);
+
+ ACE_OS::memset ((void *) (this->message_buf_ + sizeof (ACE_UINT32)),
+ 'a',
+ this->message_len_ - sizeof (ACE_UINT32));
+
+ // Allocate the barrier with the correct count.
+ ACE_MT (ACE_NEW_RETURN (this->barrier_,
+ ACE_Barrier (this->threads_),
+ -1));
+ return 0;
+}
+
+size_t
+Options::message_len (void) const
+{
+ return this->message_len_;
+}
+
+const void *
+Options::message_buf (void) const
+{
+ return this->message_buf_;
+}
+
+ssize_t
+Options::read (void *buf, size_t len, size_t &iteration)
+{
+ ACE_UNUSED_ARG (len);
+
+ if (this->io_source_ == ACE_STDIN)
+ return ACE_OS::read (ACE_STDIN, buf, len);
+ else if (iteration >= this->iterations_)
+ return 0;
+ else
+ {
+ ACE_OS::memcpy (buf,
+ this->message_buf (),
+ len);
+ iteration++;
+ return len;
+ }
+}
+
+int
+Options::parse_args (int argc, ACE_TCHAR *argv[])
+{
+ ACE_Get_Opt getopt (argc, argv, ACE_TEXT("2h:i:m:p:q:st:T:"), 1);
+
+ for (int c; (c = getopt ()) != -1; )
+ switch (c)
+ {
+ case '2': // Disable the oneway client.
+ this->oneway_ = 0;
+ break;
+ case 'h':
+ this->host_ = getopt.opt_arg ();
+ break;
+ case 'i':
+ this->iterations_ = ACE_OS::atoi (getopt.opt_arg ());
+ break;
+ case 'm':
+ this->message_len_ = ACE_OS::atoi (getopt.opt_arg ());
+ break;
+ case 'p':
+ this->port_ = ACE_OS::atoi (getopt.opt_arg ());
+ break;
+ case 'q':
+ this->quit_string_ = getopt.opt_arg ();
+ break;
+ case 's':
+ this->io_source_ = ACE_STDIN;
+ break;
+ case 't':
+ this->threads_ = (size_t) ACE_OS::atoi (getopt.opt_arg ());
+ break;
+ case 'T':
+ this->sleep_time_.set (0, ACE_OS::atoi (getopt.opt_arg ()));
+ break;
+ default:
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "(%P|%t) usage: %n [-2] [-h <host>] [-i iterations] [-m message-size] [-p <port>] [-q <quit string>] [-s] [-t <threads>] [-T <sleep_time>]\n"),
+ -1);
+ }
+
+ return this->init ();
+}
+
+u_short
+Options::port (void) const
+{
+ return this->port_;
+}
+
+const ACE_TCHAR *
+Options::host (void) const
+{
+ return this->host_;
+}
+
+const ACE_TCHAR *
+Options::quit_string (void) const
+{
+ return this->quit_string_;
+}
+
+size_t
+Options::threads (void) const
+{
+ return this->threads_;
+}
+
+const ACE_Time_Value &
+Options::sleep_time (void) const
+{
+ return this->sleep_time_;
+}
+
+char *
+Options::shared_client_test (u_short port,
+ ACE_SOCK_Stream &cli_stream)
+{
+ ACE_INET_Addr remote_addr (port, this->host_);
+
+ ACE_SOCK_Connector con;
+
+ if (con.connect (cli_stream,
+ remote_addr) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "(%P|%t) %p\n",
+ "connection failed"),
+ 0);
+ else
+ ACE_DEBUG ((LM_DEBUG,
+ "(%P|%t) connected to %s at port %d\n",
+ remote_addr.get_host_name (),
+ remote_addr.get_port_number ()));
+
+ ACE_INT32 len = htonl (this->message_len ());
+
+ // Allocate the transmit buffer.
+ char *buf;
+ ACE_DEBUG((LM_DEBUG,"(%P|%t) allocating buffer, len = %d msglen = %d\n",
+ len, message_len_));
+
+ ACE_NEW_RETURN (buf,
+ char[this->message_len()],
+ 0);
+
+ ACE_DEBUG ((LM_DEBUG,
+ "(%P|%t) waiting...\n"));
+
+ // Wait for all other threads to finish initialization.
+ ACE_MT (this->barrier_->wait ());
+ return buf;
+}
+// Static function entry point to the oneway client service.
+
+void *
+Options::oneway_client_test (void *)
+{
+ Options *options = OPTIONS::instance ();
+ ACE_SOCK_Stream cli_stream;
+
+ ACE_DEBUG((LM_DEBUG,"options = %d, len = %d\n",options,options->message_len()));
+
+ // Add 1 to the port to trigger the oneway test!
+ char *request = options->shared_client_test (options->port () + 1,
+ cli_stream);
+ if (request == 0)
+ return 0;
+
+ // This variable is allocated off the stack to obviate the need for
+ // locking.
+ size_t iteration = 0;
+
+ // Keep track of return value.
+ int result = 0;
+ ACE_INT32 len = options->message_len ();
+
+ ACE_DEBUG ((LM_DEBUG,
+ "(%P|%t) starting oneway transmission\n"));
+
+ // Perform oneway transmission of data to server (correctly handles
+ // "incomplete writes").
+
+ for (ssize_t r_bytes;
+ (r_bytes = options->read (request, len, iteration)) > 0;
+ // Transmit at the proper rate.
+ ACE_OS::sleep (options->sleep_time ()))
+ if (ACE_OS::memcmp (request,
+ options->quit_string (),
+ ACE_OS::strlen (options->quit_string ())) == 0)
+ break;
+ else if (cli_stream.send_n (request, r_bytes) == -1)
+ {
+ ACE_ERROR ((LM_ERROR,
+ "(%P|%t) %p\n",
+ "send_n"));
+ result = -1;
+ break;
+ }
+
+ // Close the connection.
+ cli_stream.close ();
+
+ delete [] request;
+ return reinterpret_cast<void *> (result);
+}
+
+// Static function entry point to the twoway client service.
+
+void *
+Options::twoway_client_test (void *)
+{
+ Options *options = OPTIONS::instance ();
+
+ ACE_SOCK_Stream cli_stream;
+
+ char *request = options->shared_client_test (options->port (),
+ cli_stream);
+ if (request == 0)
+ return 0;
+
+ // This variable is allocated off the stack to obviate the need for
+ // locking.
+ size_t iteration = 0;
+
+ // Keep track of return value.
+ int result = 0;
+
+ // Timer business.
+ ACE_High_Res_Timer timer;
+
+ ACE_INT32 len = options->message_len ();
+
+ ACE_DEBUG ((LM_DEBUG,
+ "(%P|%t) starting twoway transmission\n"));
+
+ // Perform twoway transmission of data to server (correctly handles
+ // "incomplete writes").
+
+ for (ssize_t r_bytes;
+ (r_bytes = options->read (request, len, iteration)) > 0;
+ // Transmit at the proper rate.
+ ACE_OS::sleep (options->sleep_time ()))
+ if (ACE_OS::memcmp (request,
+ options->quit_string (),
+ ACE_OS::strlen (options->quit_string ())) == 0)
+ break;
+
+ // Transmit <request> to the server.
+ else
+ {
+ // Note that we use the incremental feature of the
+ // <ACE_High_Res_Timer> so that we don't get "charged" for the
+ // <ACE_OS::sleep> used to control the rate at which requests
+ // are sent.
+ timer.start_incr ();
+
+ if (cli_stream.send_n (request, r_bytes) == -1)
+ {
+ ACE_ERROR ((LM_ERROR,
+ "(%P|%t) %p\n",
+ "send_n"));
+ result = -1;
+ break;
+ }
+ // Receive the reply from the server. Normally, it just sends
+ // back 24 bytes, which is typical for an IIOP reply.
+ else if (cli_stream.recv (request, r_bytes) <= 0)
+ {
+ ACE_ERROR ((LM_ERROR,
+ "(%P|%t) %p\n",
+ "recv"));
+ result = -1;
+ break;
+ }
+
+ timer.stop_incr ();
+ }
+
+ ACE_Time_Value tv;
+
+ timer.elapsed_time_incr (tv);
+ double real_time = tv.sec () * ACE_ONE_SECOND_IN_USECS + tv.usec ();
+ double messages_per_sec = iteration * double (ACE_ONE_SECOND_IN_USECS) / real_time;
+
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("(%t) messages = %d\n(%t) usec-per-message = %f\n(%t) messages-per-second = %0.00f\n"),
+ iteration,
+ real_time / double (iteration),
+ messages_per_sec < 0 ? 0 : messages_per_sec));
+
+ // Close the connection.
+ cli_stream.close ();
+
+ delete [] request;
+ return reinterpret_cast<void *> (result);
+}
+
+ACE_THR_FUNC
+Options::thr_func (void)
+{
+ ACE_DEBUG((LM_DEBUG,"(%P|%t) in thread func, mesg len = %d\n",this->message_len()));
+ if (this->oneway_ == 0)
+ return ACE_THR_FUNC (&Options::twoway_client_test);
+ else
+ return ACE_THR_FUNC (&Options::oneway_client_test);
+}
+
+static int
+run_client (void)
+{
+ // Raise the socket handle limit to the maximum.
+ ACE::set_handle_limit ();
+
+#if defined (ACE_HAS_THREADS)
+ ACE_DEBUG((LM_DEBUG,"(%P|%t) spawning client test thread options = %d\n",
+ OPTIONS::instance()));
+
+ if (ACE_Thread_Manager::instance ()->spawn_n (OPTIONS::instance ()->threads (),
+ OPTIONS::instance ()->thr_func ()) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "(%P|%t) %p\n",
+ "spawn_n"),
+ 1);
+ else
+ ACE_Thread_Manager::instance ()->wait ();
+#else
+ *(OPTIONS::instance ()->thr_func) ();
+#endif /* ACE_HAS_THREADS */
+ return 0;
+}
+
+int
+ACE_TMAIN (int argc, ACE_TCHAR *argv[])
+{
+ // Initialize the logger.
+ ACE_LOG_MSG->open (argv[0]);
+
+ if (OPTIONS::instance ()->parse_args (argc, argv) == -1)
+ return -1;
+
+ // Run the client
+ run_client ();
+
+ return 0;
+}
+
+#if defined (ACE_HAS_EXPLICIT_STATIC_TEMPLATE_MEMBER_INSTANTIATION)
+template ACE_Singleton<Options, ACE_SYNCH_RECURSIVE_MUTEX> *
+ ACE_Singleton<Options, ACE_SYNCH_RECURSIVE_MUTEX>::singleton_;
+#endif /* ACE_HAS_EXPLICIT_STATIC_TEMPLATE_MEMBER_INSTANTIATION */
diff --git a/ACE/examples/IPC_SAP/SOCK_SAP/CPP-inclient.h b/ACE/examples/IPC_SAP/SOCK_SAP/CPP-inclient.h
new file mode 100644
index 00000000000..7486c70b749
--- /dev/null
+++ b/ACE/examples/IPC_SAP/SOCK_SAP/CPP-inclient.h
@@ -0,0 +1,108 @@
+// $Id$
+
+// This file defines the Options class for CPP-inclient. IBM C++ compiler'd
+// template auto-instantiator needs this in a separate file.
+
+#ifndef __CPP_INCLIENT_H
+#define __CPP_INCLIENT_H
+
+#include "ace/SOCK_Stream.h"
+#include "ace/Barrier.h"
+#include "ace/Time_Value.h"
+
+class Options
+ // = TITLE
+ // Define the options for this test.
+{
+public:
+ Options (void);
+ // Constructor.
+
+ ~Options (void);
+ // Destructor.
+
+ int parse_args (int argc, ACE_TCHAR *argv[]);
+ // Parse the command-line arguments.
+
+ const ACE_Time_Value &sleep_time (void) const;
+ // Return the amount of time to sleep in order to implement the
+ // proper transmission rates.
+
+ u_short port (void) const;
+ // Port of the server.
+
+ const ACE_TCHAR *host (void) const;
+ // Host of the server.
+
+ size_t threads (void) const;
+ // Number of threads.
+
+ const ACE_TCHAR *quit_string (void) const;
+ // String that shuts down the client/server.
+
+ ssize_t read (void *buf, size_t len, size_t &iterations);
+ // Read from the appropriate location.
+
+ size_t message_len (void) const;
+ // Returns the length of the message to send.
+
+ const void *message_buf (void) const;
+ // Returns a pointer to the message.
+
+ ACE_THR_FUNC thr_func (void);
+ // Returns a pointer to the entry point into the thread that runs
+ // the client test function.
+
+private:
+ int init (void);
+ // Initialize the message we're sending to the user and set up the
+ // barrier.
+
+ char *shared_client_test (u_short port,
+ ACE_SOCK_Stream &cli_stream);
+ // Performs the shared behavior of the oneway and twoway client
+ // tests.
+
+ static void *twoway_client_test (void *);
+ // Performs the twoway test.
+
+ static void *oneway_client_test (void *);
+ // Performs the oneway test.
+
+ const ACE_TCHAR *host_;
+ // Host of the server.
+
+ u_short port_;
+ // Port of the server.
+
+ ACE_Time_Value sleep_time_;
+ // Sleep_Time value.
+
+ size_t threads_;
+ // Number of threads.
+
+ const ACE_TCHAR *quit_string_;
+ // String that shuts down the client/server.
+
+ size_t message_len_;
+ // Size of the message we send to the server.
+
+ char *message_buf_;
+ // Pointer to the message we send to the server.
+
+ ACE_HANDLE io_source_;
+ // Are we reading I/O from ACE_STDIN or from our generator?
+
+ size_t iterations_;
+ // Number of iterations.
+
+ char oneway_;
+ // Are we running oneway or twoway?
+
+ // Please leave the ; inside the parenthesis to avoid Green Hills
+ // (and probably other) compiler warning about extra ;.
+ ACE_MT (ACE_Barrier *barrier_;)
+ // Barrier used to synchronize the start of all the threads.
+};
+
+#endif /* __CPP_INCLIENT_H */
diff --git a/ACE/examples/IPC_SAP/SOCK_SAP/CPP-inserver-fancy.cpp b/ACE/examples/IPC_SAP/SOCK_SAP/CPP-inserver-fancy.cpp
new file mode 100644
index 00000000000..43df0572f74
--- /dev/null
+++ b/ACE/examples/IPC_SAP/SOCK_SAP/CPP-inserver-fancy.cpp
@@ -0,0 +1,582 @@
+ // $Id$
+
+// This example tests the features of the <ACE_SOCK_Acceptor>,
+// <ACE_SOCK_Stream>, and <ACE_Svc_Handler> classes. If the platform
+// supports threads it uses a thread-per-connection concurrency model.
+// Otherwise, it uses a single-threaded iterative server model.
+
+#include "ace/OS_main.h"
+#include "ace/SOCK_Acceptor.h"
+#include "ace/Svc_Handler.h"
+#include "ace/Singleton.h"
+#include "ace/Profile_Timer.h"
+#include "ace/Get_Opt.h"
+#include "ace/OS_NS_sys_select.h"
+
+#include "CPP-inserver-fancy.h"
+
+ACE_RCSID(SOCK_SAP, CPP_inserver_fancy, "$Id$")
+
+// Forward declaration.
+class Handler;
+
+class Handler_Factory
+{
+ // = TITLE
+ // Creates the oneway or twoway handlers.
+public:
+ Handler_Factory (void);
+ // Constructor.
+
+ ~Handler_Factory (void);
+ // Destructor.
+
+ int handle_events (void);
+ // Run the main event loop.
+
+private:
+ int init_acceptors (void);
+ // Initialize the acceptors.
+
+ int create_handler (ACE_SOCK_Acceptor &acceptor,
+ Handler *(*handler_factory) (ACE_HANDLE),
+ const char *handler_type);
+ // Factory that creates the right kind of <Handler>.
+
+ // = Factory functions.
+ static Handler *make_twoway_handler (ACE_HANDLE);
+ // Create a twoway handler.
+
+ static Handler *make_oneway_handler (ACE_HANDLE);
+ // Create a oneway handler.
+
+ ACE_SOCK_Acceptor twoway_acceptor_;
+ // Twoway acceptor factory.
+
+ ACE_SOCK_Acceptor oneway_acceptor_;
+ // Oneway acceptor factory.
+};
+
+class Handler : public ACE_Svc_Handler<ACE_SOCK_STREAM, ACE_NULL_SYNCH>
+{
+ // = TITLE
+ // Base class for the oneway and twoway handlers.
+
+ friend class Handler_Factory;
+ // The factory has special permission. (to access svc ()).
+
+public:
+ virtual int open (void * = 0);
+ // Generic initialization method.
+
+ virtual int close (u_long);
+ // Close down and delete this.
+
+protected:
+ Handler (ACE_HANDLE handle);
+ // Constructor.
+
+ int parse_header_and_allocate_buffer (char *&buf,
+ ACE_INT32 *len);
+ // Implement the generic code that's called from any of the subclass
+ // <run> methods to get the header and the buffer to read the data.
+ // This method factors out common code.
+
+ virtual int run (void) = 0;
+ // Hook method called by the <svc> template method to do the actual
+ // protocol. Must be overridden by the subclass.
+
+ virtual int svc (void);
+ // Template method entry point into the handler task.
+
+ virtual void print_results (void);
+ // Print the results.
+
+ size_t total_bytes_;
+ // Total number of bytes received.
+
+ size_t message_count_;
+ // Number of messages received.
+
+ ACE_Profile_Timer timer_;
+ // Keeps track of how much time we're using.
+};
+
+class Twoway_Handler : public Handler
+{
+ // = TITLE
+ // Performs the twoway protocol.
+public:
+ Twoway_Handler (ACE_HANDLE handle);
+ // Constructor.
+
+private:
+ virtual int run (void);
+ // Template Method hook called by <svc>.
+};
+
+class Oneway_Handler : public Handler
+{
+ // = TITLE
+public:
+ Oneway_Handler (ACE_HANDLE handle);
+ // Constructor.
+
+private:
+ virtual int run (void);
+ // Template Method hook called by <svc>.
+
+ virtual void print_results (void);
+ // Print the results.
+};
+
+u_short
+Options::port (void) const
+{
+ return this->port_;
+}
+
+int
+Options::verbose (void) const
+{
+ return this->verbose_;
+}
+
+int
+Options::reply_message_len (void) const
+{
+ return this->reply_message_len_;
+}
+
+Options::~Options (void)
+{
+}
+
+Options::Options (void)
+ : verbose_ (0),
+ port_ (ACE_DEFAULT_SERVER_PORT),
+ reply_message_len_ (24) // Default to the approximate size of an
+ // GIOP reply message.
+{
+}
+
+int
+Options::parse_args (int argc, ACE_TCHAR *argv[])
+{
+ ACE_Get_Opt getopt (argc, argv, ACE_TEXT("p:r:v"), 1);
+
+ for (int c; (c = getopt ()) != -1; )
+ switch (c)
+ {
+ case 'p':
+ this->port_ = ACE_OS::atoi (getopt.opt_arg ());
+ break;
+ case 'r':
+ this->reply_message_len_ = ACE_OS::atoi (getopt.opt_arg ());
+ break;
+ case 'v':
+ this->verbose_ = 1;
+ break;
+ default:
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "(%P|%t) usage: %n [-p <port>] [-v]"),
+ -1);
+ }
+
+ return 0;
+}
+
+// Options Singleton.
+typedef ACE_Singleton<Options, ACE_SYNCH_RECURSIVE_MUTEX> OPTIONS;
+
+Handler::Handler (ACE_HANDLE handle)
+ : total_bytes_ (0),
+ message_count_ (0)
+{
+ this->peer ().set_handle (handle);
+}
+
+int
+Handler::open (void *)
+{
+ ACE_INET_Addr cli_addr;
+
+ // Make sure we're not in non-blocking mode.
+ if (this->peer ().disable (ACE_NONBLOCK) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%p\n",
+ "disable"),
+ 0);
+
+ ACE_DEBUG ((LM_DEBUG,
+ "(%P|%t) client %s connected from %d on handle %d\n",
+ cli_addr.get_host_name (),
+ cli_addr.get_port_number (),
+ this->peer ().get_handle ()));
+ return 0;
+}
+
+int
+Handler::close (u_long)
+{
+ ACE_DEBUG ((LM_DEBUG,
+ "(%P|%t) closing down %x\n",
+ this));
+ delete this;
+ return 0;
+}
+
+int
+Handler::svc (void)
+{
+ // Timer logic.
+ this->timer_.start ();
+
+ // Invoke the hook method to run the specific test.
+ int result = this->run ();
+
+ this->timer_.stop ();
+
+ this->print_results ();
+
+ return result;
+}
+
+int
+Handler::parse_header_and_allocate_buffer (char *&request,
+ ACE_INT32 *len)
+{
+ ssize_t result = this->peer ().recv_n ((void *) len,
+ sizeof (ACE_INT32));
+ if (result == 0)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ "(%P|%t) connected closed\n"));
+ return -1;
+ }
+ else if (result == -1 || result != sizeof (ACE_INT32))
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "(%P|%t) %p\n",
+ "recv_n failed"),
+ -1);
+ else
+ {
+ *len = ntohl (*len);
+ ACE_NEW_RETURN (request,
+ char[*len],
+ -1);
+ }
+
+ return 0;
+}
+
+void
+Handler::print_results (void)
+{
+}
+
+Twoway_Handler::Twoway_Handler (ACE_HANDLE handle)
+ : Handler (handle)
+{
+}
+
+// Function entry point into the twoway server task.
+
+int
+Twoway_Handler::run (void)
+{
+ // Read data from client (terminate on error).
+
+ char *request = 0;
+
+ for (;;)
+ {
+ ACE_INT32 len = 0;
+
+ if (parse_header_and_allocate_buffer (request,
+ &len) == -1)
+ return -1;
+
+ // Subtract off the sizeof the length prefix.
+ ssize_t r_bytes = this->peer ().recv_n (request,
+ len - sizeof (ACE_UINT32));
+
+ if (r_bytes == -1)
+ {
+ ACE_ERROR ((LM_ERROR,
+ "%p\n",
+ "recv"));
+ break;
+ }
+ else if (r_bytes == 0)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ "(%P|%t) reached end of input, connection closed by client\n"));
+ break;
+ }
+ else if (OPTIONS::instance ()->verbose ()
+ && ACE::write_n (ACE_STDOUT,
+ request,
+ r_bytes) != r_bytes)
+ ACE_ERROR ((LM_ERROR,
+ "%p\n",
+ "ACE::write_n"));
+ else
+ {
+ ssize_t s_bytes = (ssize_t) OPTIONS::instance ()->reply_message_len ();
+
+ // Don't try to send more than is in the request buffer!
+ if (s_bytes > r_bytes)
+ s_bytes = r_bytes;
+
+ if (this->peer ().send_n (request,
+ s_bytes) != s_bytes)
+ ACE_ERROR ((LM_ERROR,
+ "%p\n",
+ "send_n"));
+ }
+ this->total_bytes_ += size_t (r_bytes);
+ this->message_count_++;
+
+ delete [] request;
+ request = 0;
+ }
+
+ delete [] request;
+ return 0;
+}
+
+Oneway_Handler::Oneway_Handler (ACE_HANDLE handle)
+ : Handler (handle)
+{
+}
+
+void
+Oneway_Handler::print_results (void)
+{
+ ACE_Profile_Timer::ACE_Elapsed_Time et;
+ this->timer_.elapsed_time (et);
+
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("\t\treal time = %f secs \n\t\tuser time = %f secs \n\t\tsystem time = %f secs\n"),
+ et.real_time,
+ et.user_time,
+ et.system_time));
+
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("\t\tmessages = %d\n\t\ttotal bytes = %d\n\t\tmbits/sec = %f\n\t\tusec-per-message = %f\n"),
+ this->message_count_,
+ this->total_bytes_,
+ (((double) this->total_bytes_ * 8) / et.real_time) / (double) (1024 * 1024),
+ ((et.user_time + et.system_time) / (double) this->message_count_) * ACE_ONE_SECOND_IN_USECS));
+}
+
+// Function entry point into the oneway server task.
+
+int
+Oneway_Handler::run (void)
+{
+ // Read data from client (terminate on error).
+
+ char *request = 0;
+
+ for (;;)
+ {
+ ACE_INT32 len = 0;
+
+ if (parse_header_and_allocate_buffer (request,
+ &len) == -1)
+ return -1;
+
+ // Subtract off the sizeof the length prefix.
+ ssize_t r_bytes = this->peer ().recv_n (request,
+ len - sizeof (ACE_UINT32));
+
+ if (r_bytes == -1)
+ {
+ ACE_ERROR ((LM_ERROR,
+ "%p\n",
+ "recv"));
+ break;
+ }
+ else if (r_bytes == 0)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ "(%P|%t) reached end of input, connection closed by client\n"));
+ break;
+ }
+ else if (OPTIONS::instance ()->verbose ()
+ && ACE::write_n (ACE_STDOUT,
+ request,
+ r_bytes) != r_bytes)
+ ACE_ERROR ((LM_ERROR,
+ "%p\n",
+ "ACE::write_n"));
+
+ this->total_bytes_ += size_t (r_bytes);
+ this->message_count_++;
+ delete [] request;
+ request = 0;
+ }
+
+ delete [] request;
+ return 0;
+}
+
+// Create a twoway handler.
+
+Handler *
+Handler_Factory::make_twoway_handler (ACE_HANDLE handle)
+{
+ return new Twoway_Handler (handle);
+}
+
+// Create a oneway handler.
+
+Handler *
+Handler_Factory::make_oneway_handler (ACE_HANDLE handle)
+{
+ return new Oneway_Handler (handle);
+}
+
+int
+Handler_Factory::init_acceptors (void)
+{
+ // Create the oneway and twoway server addresses.
+ ACE_INET_Addr twoway_server_addr (OPTIONS::instance ()->port ());
+ ACE_INET_Addr oneway_server_addr (OPTIONS::instance ()->port () + 1);
+
+ // Create acceptors, reuse the address.
+ if (this->twoway_acceptor_.open (twoway_server_addr, 1) == -1
+ || this->oneway_acceptor_.open (oneway_server_addr, 1) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%p\n",
+ "open"),
+ -1);
+ else if (this->twoway_acceptor_.get_local_addr (twoway_server_addr) == -1
+ || this->oneway_acceptor_.get_local_addr (oneway_server_addr) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%p\n",
+ "get_local_addr"),
+ -1);
+ ACE_DEBUG ((LM_DEBUG,
+ "(%P|%t) starting twoway server at port %d and oneway server at port %d\n",
+ twoway_server_addr.get_port_number (),
+ oneway_server_addr.get_port_number ()));
+ return 0;
+}
+
+int
+Handler_Factory::create_handler (ACE_SOCK_Acceptor &acceptor,
+ Handler * (*handler_factory) (ACE_HANDLE),
+ const char *handler_type)
+{
+ ACE_SOCK_Stream new_stream;
+
+ if (acceptor.accept (new_stream) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%p\n",
+ "accept"),
+ -1);
+
+ Handler *handler;
+
+ ACE_ALLOCATOR_RETURN (handler,
+ (*handler_factory) (new_stream.get_handle ()),
+ -1);
+
+ ACE_DEBUG ((LM_DEBUG,
+ "(%P|%t) spawning %s handler\n",
+ handler_type));
+
+ if (handler->open () == -1)
+ return -1;
+
+#if defined (ACE_MT_SAFE)
+ // Spawn a new thread and run the new connection in that thread of
+ // control using the <server> function as the entry point.
+ return handler->activate ();
+#else
+ handler->svc ();
+ handler->close (0);
+ return 0;
+#endif /* ACE_HAS_THREADS */
+}
+
+Handler_Factory::Handler_Factory (void)
+{
+}
+
+Handler_Factory::~Handler_Factory (void)
+{
+ this->twoway_acceptor_.close ();
+ this->oneway_acceptor_.close ();
+}
+
+// Run the main event loop.
+
+int
+Handler_Factory::handle_events (void)
+{
+ if (this->init_acceptors () == -1)
+ return -1;
+
+ fd_set handles;
+
+ FD_ZERO (&handles);
+ FD_SET ((ACE_SOCKET) this->twoway_acceptor_.get_handle (),
+ &handles);
+ FD_SET ((ACE_SOCKET) this->oneway_acceptor_.get_handle (),
+ &handles);
+
+ // Performs the iterative server activities.
+
+ for (;;)
+ {
+ ACE_Time_Value timeout (ACE_DEFAULT_TIMEOUT);
+ fd_set temp = handles;
+
+ int result = ACE_OS::select (int (this->oneway_acceptor_.get_handle ()) + 1,
+ (fd_set *) &temp,
+ 0,
+ 0,
+ timeout);
+ if (result == -1)
+ ACE_ERROR ((LM_ERROR,
+ "(%P|%t) %p\n",
+ "select"));
+ else if (result == 0 && OPTIONS::instance ()->verbose ())
+ ACE_DEBUG ((LM_DEBUG,
+ "(%P|%t) select timed out\n"));
+ else
+ {
+ if (FD_ISSET ((ACE_SOCKET) this->twoway_acceptor_.get_handle (),
+ &temp))
+ this->create_handler (this->twoway_acceptor_,
+ &Handler_Factory::make_twoway_handler,
+ "twoway");
+ if (FD_ISSET ((ACE_SOCKET) this->oneway_acceptor_.get_handle (),
+ &temp))
+ this->create_handler (this->oneway_acceptor_,
+ &Handler_Factory::make_oneway_handler,
+ "oneway");
+ }
+ }
+
+ ACE_NOTREACHED (return 0;)
+}
+
+int
+ACE_TMAIN (int argc, ACE_TCHAR *argv[])
+{
+ OPTIONS::instance ()->parse_args (argc, argv);
+
+ Handler_Factory server;
+
+ return server.handle_events ();
+}
+
+#if defined (ACE_HAS_EXPLICIT_STATIC_TEMPLATE_MEMBER_INSTANTIATION)
+template ACE_Singleton<Options, ACE_SYNCH_RECURSIVE_MUTEX> *
+ ACE_Singleton<Options, ACE_SYNCH_RECURSIVE_MUTEX>::singleton_;
+#endif /* ACE_HAS_EXPLICIT_STATIC_TEMPLATE_MEMBER_INSTANTIATION */
diff --git a/ACE/examples/IPC_SAP/SOCK_SAP/CPP-inserver-fancy.h b/ACE/examples/IPC_SAP/SOCK_SAP/CPP-inserver-fancy.h
new file mode 100644
index 00000000000..9901bcc0b20
--- /dev/null
+++ b/ACE/examples/IPC_SAP/SOCK_SAP/CPP-inserver-fancy.h
@@ -0,0 +1,43 @@
+// $Id$
+
+// This file defines the Options class for CPP-inserver-fancy.
+// IBM C++ compiler'd template auto-instantiator needs this in a separate file.
+
+#ifndef __CPP_INSERVER_FANCY_H
+#define __CPP_INSERVER_FANCY_H
+
+class Options
+ // = TITLE
+ // Define the options for this test.
+{
+public:
+ Options (void);
+ // Constructor.
+
+ ~Options (void);
+ // Destructor.
+
+ int parse_args (int argc, ACE_TCHAR *argv[]);
+ // Parse the command-line arguments.
+
+ int verbose (void) const;
+ // Are we running in verbose mode?
+
+ u_short port (void) const;
+ // Port number that we are listening at.
+
+ int reply_message_len (void) const;
+ // Size of the reply message.
+
+private:
+ int verbose_;
+ // Are we running in verbose mode?
+
+ u_short port_;
+ // Port number we listen at.
+
+ size_t reply_message_len_;
+ // Size of the reply message.
+};
+
+#endif /* __CPP_INSERVER_FANCY_H */
diff --git a/ACE/examples/IPC_SAP/SOCK_SAP/CPP-inserver-poll.cpp b/ACE/examples/IPC_SAP/SOCK_SAP/CPP-inserver-poll.cpp
new file mode 100644
index 00000000000..a281d2e380d
--- /dev/null
+++ b/ACE/examples/IPC_SAP/SOCK_SAP/CPP-inserver-poll.cpp
@@ -0,0 +1,207 @@
+// $Id$
+
+// IPC_SAP/poll server, which illustrates how to integrate the ACE
+// socket wrappers with the SVR4 <poll> system call to create a
+// single-threaded concurrent server. This server program can be
+// driven by the oneway test mode of CPP-inclient.cpp.
+
+#include "ace/OS_main.h"
+#include "ace/SOCK_Acceptor.h"
+#include "ace/SOCK_Stream.h"
+#include "ace/INET_Addr.h"
+#include "ace/Log_Msg.h"
+#include "ace/OS_NS_poll.h"
+#include "ace/OS_NS_stdio.h"
+
+ACE_RCSID(SOCK_SAP, CPP_inserver_poll, "$Id$")
+
+#if defined (ACE_HAS_POLL)
+
+// Should we be verbose?
+static int verbose = 0;
+
+// Max number of open handles.
+static const int MAX_HANDLES = 200;
+
+struct Buffer_Info
+{
+ void *buf_;
+ // Pointer to the buffer.
+
+ size_t len_;
+ // Length of the buffer.
+};
+
+// Array of <pollfd>'s.
+static struct pollfd poll_array[MAX_HANDLES];
+
+// Array of <Buffer_Info>.
+static Buffer_Info buffer_array[MAX_HANDLES];
+
+static void
+init_poll_array (void)
+{
+ int i;
+
+ for (i = 0; i < MAX_HANDLES; i++)
+ {
+ poll_array[i].fd = ACE_INVALID_HANDLE;
+ poll_array[i].events = POLLIN;
+ }
+}
+
+static int
+init_buffer (size_t index)
+{
+ ACE_INT32 len;
+
+ if (ACE::recv_n (poll_array[index].fd,
+ (void *) &len,
+ sizeof (ACE_INT32)) != sizeof (ACE_INT32))
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "(%P|%t) %p\n",
+ "recv_n failed"),
+ -1);
+ else
+ {
+ len = ntohl (len);
+ ACE_DEBUG ((LM_DEBUG,
+ "(%P|%t) reading messages of size %d from handle %d\n",
+ len,
+ poll_array[index].fd));
+
+ ACE_ALLOCATOR_RETURN (buffer_array[index].buf_,
+ ACE_OS::malloc (len),
+ -1);
+ buffer_array[index].len_ = len;
+ }
+ return 0;
+}
+
+static void
+handle_data (size_t &n_handles)
+{
+ // Handle pending logging messages first (s_handle + 1 is guaranteed
+ // to be lowest client descriptor).
+
+ for (size_t index = 1; index < n_handles; index++)
+ {
+ if (ACE_BIT_ENABLED (poll_array[index].revents, POLLIN))
+ {
+ // First time in, we need to initialize the buffer.
+ if (buffer_array[index].buf_ == 0
+ && init_buffer (index) == -1)
+ {
+ ACE_ERROR ((LM_ERROR,
+ "(%P|%t) %p\n",
+ "init_buffer"));
+ continue;
+ }
+
+ // Read data from client (terminate on error).
+
+ ssize_t n = ACE::recv (poll_array[index].fd,
+ buffer_array[index].buf_,
+ buffer_array[index].len_);
+ // <recv> will not block in this case!
+
+ if (n == -1)
+ ACE_ERROR ((LM_ERROR,
+ "%p\n",
+ "read failed"));
+ else if (n == 0)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ "(%P|%t) closing oneway server at handle %d\n",
+ poll_array[index].fd));
+
+ // Handle client connection shutdown.
+ ACE_OS::close (poll_array[index].fd);
+ poll_array[index].fd = poll_array[--n_handles].fd;
+
+ ACE_OS::free ((void *) buffer_array[index].buf_);
+ buffer_array[index].buf_ = 0;
+ buffer_array[index].len_ = 0;
+ }
+ else if (verbose)
+ ACE_DEBUG ((LM_DEBUG,
+ "(%P|%t) %*s",
+ n,
+ buffer_array[index].buf_));
+ }
+ }
+}
+
+static void
+handle_connections (ACE_SOCK_Acceptor &peer_acceptor,
+ size_t &n_handles)
+{
+ if (ACE_BIT_ENABLED (poll_array[0].revents, POLLIN))
+ {
+ ACE_SOCK_Stream new_stream;
+
+ ACE_INET_Addr client;
+ ACE_Time_Value nonblock (0, 0);
+
+ // Handle all pending connection requests (note use of "polling"
+ // feature that doesn't block).
+
+ while (ACE_OS::poll (poll_array, 1, nonblock) > 0)
+ if (peer_acceptor.accept (new_stream, &client) == -1)
+ ACE_OS::perror ("accept");
+ else
+ {
+ const char *s = client.get_host_name ();
+
+ ACE_ASSERT (s != 0);
+ ACE_DEBUG ((LM_DEBUG,
+ "(%P|%t) client %s\n",
+ s));
+ poll_array[n_handles++].fd = new_stream.get_handle ();
+ }
+ }
+}
+
+int
+ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ u_short port = ACE_DEFAULT_SERVER_PORT + 1;
+
+ // Create a server end-point.
+ ACE_INET_Addr addr (port);
+ ACE_SOCK_Acceptor peer_acceptor (addr);
+
+ ACE_HANDLE s_handle = peer_acceptor.get_handle ();
+
+ init_poll_array ();
+
+ poll_array[0].fd = s_handle;
+
+ ACE_DEBUG ((LM_DEBUG,
+ "(%P|%t) starting oneway server at port %d\n",
+ port));
+
+ for (size_t n_handles = 1;;)
+ {
+ ACE_ENDLESS_LOOP
+
+ // Wait for client I/O events (handle interrupts).
+ while (ACE_OS::poll (poll_array, n_handles) == -1
+ && errno == EINTR)
+ continue;
+
+ handle_data (n_handles);
+ handle_connections (peer_acceptor, n_handles);
+ }
+
+ /* NOTREACHED */
+ return 0;
+}
+#else
+#include <stdio.h>
+int ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ ACE_OS::fprintf (stderr, "This feature is not supported\n");
+ return 0;
+}
+#endif /* ACE_HAS_POLL */
diff --git a/ACE/examples/IPC_SAP/SOCK_SAP/CPP-inserver.cpp b/ACE/examples/IPC_SAP/SOCK_SAP/CPP-inserver.cpp
new file mode 100644
index 00000000000..b978bb5f989
--- /dev/null
+++ b/ACE/examples/IPC_SAP/SOCK_SAP/CPP-inserver.cpp
@@ -0,0 +1,391 @@
+// $Id$
+
+// This example tests the features of the <ACE_SOCK_Acceptor>,
+// <ACE_SOCK_Stream>, and <ACE_Svc_Handler> classes. If the platform
+// supports threads it uses a thread-per-connection concurrency model.
+// Otherwise, it uses a single-threaded iterative server model.
+
+#include "ace/SOCK_Acceptor.h"
+#include "ace/Thread_Manager.h"
+#include "ace/Handle_Set.h"
+#include "ace/Profile_Timer.h"
+#include "ace/OS_NS_sys_select.h"
+#include "ace/OS_main.h"
+
+ACE_RCSID(SOCK_SAP, CPP_inserver, "$Id$")
+
+// Are we running verbosely?
+static int verbose = 0;
+
+static void
+run_server (ACE_THR_FUNC server,
+ ACE_HANDLE handle)
+{
+#if defined (ACE_HAS_THREADS)
+ // Spawn a new thread and run the new connection in that thread of
+ // control using the <server> function as the entry point.
+ if (ACE_Thread_Manager::instance ()->spawn (server,
+ reinterpret_cast<void *> (handle),
+ THR_DETACHED) == -1)
+ ACE_ERROR ((LM_ERROR,
+ "(%P|%t) %p\n",
+ "spawn"));
+#else
+ (*server) (reinterpret_cast<void *> (handle));
+#endif /* ACE_HAS_THREADS */
+}
+
+// Function entry point into the twoway server task.
+
+static ACE_THR_FUNC_RETURN
+twoway_server (void *arg)
+{
+ ACE_INET_Addr cli_addr;
+ ACE_SOCK_Stream new_stream;
+ ACE_HANDLE handle = (ACE_HANDLE) (long) arg;
+
+ new_stream.set_handle (handle);
+
+ // Make sure we're not in non-blocking mode.
+ if (new_stream.disable (ACE_NONBLOCK) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%p\n",
+ "disable"),
+ 0);
+ else if (new_stream.get_remote_addr (cli_addr) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%p\n",
+ "get_remote_addr"),
+ 0);
+
+ ACE_DEBUG ((LM_DEBUG,
+ "(%P|%t) client %s connected from %d\n",
+ cli_addr.get_host_name (),
+ cli_addr.get_port_number ()));
+
+ size_t total_bytes = 0;
+ size_t message_count = 0;
+
+ char *request = 0;
+
+ // Read data from client (terminate on error).
+
+ for (;;)
+ {
+ ACE_INT32 len;
+
+ ssize_t r_bytes = new_stream.recv_n ((void *) &len,
+ sizeof (ACE_INT32));
+ if (r_bytes == -1)
+ {
+ ACE_ERROR ((LM_ERROR,
+ "%p\n",
+ "recv"));
+ break;
+ }
+ else if (r_bytes == 0)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ "(%P|%t) reached end of input, connection closed by client\n"));
+ break;
+ }
+ else if (r_bytes != sizeof (ACE_INT32))
+ {
+ ACE_ERROR ((LM_ERROR,
+ "(%P|%t) %p\n",
+ "recv_n failed"));
+ break;
+ }
+ else
+ {
+ len = ntohl (len);
+ ACE_NEW_RETURN (request,
+ char [len],
+ 0);
+ }
+
+ // Subtract off the sizeof the length prefix.
+ r_bytes = new_stream.recv_n (request,
+ len - sizeof (ACE_UINT32));
+ if (r_bytes == -1)
+ {
+ ACE_ERROR ((LM_ERROR,
+ "%p\n",
+ "recv"));
+ break;
+ }
+ else if (r_bytes == 0)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ "(%P|%t) reached end of input, connection closed by client\n"));
+ break;
+ }
+ else if (verbose
+ && ACE::write_n (ACE_STDOUT,
+ request,
+ r_bytes) != r_bytes)
+ ACE_ERROR ((LM_ERROR,
+ "%p\n",
+ "ACE::write_n"));
+ else if (new_stream.send_n (request,
+ r_bytes) != r_bytes)
+ ACE_ERROR ((LM_ERROR,
+ "%p\n",
+ "send_n"));
+
+ total_bytes += size_t (r_bytes);
+ message_count++;
+
+ delete [] request;
+ request = 0;
+ }
+
+ // Close new endpoint (listening endpoint stays open).
+ new_stream.close ();
+
+ delete [] request;
+ return 0;
+}
+
+// Function entry point into the oneway server task.
+
+static ACE_THR_FUNC_RETURN
+oneway_server (void *arg)
+{
+ ACE_INET_Addr cli_addr;
+ ACE_SOCK_Stream new_stream;
+ ACE_HANDLE handle = (ACE_HANDLE) (long) arg;
+
+ new_stream.set_handle (handle);
+
+ // Make sure we're not in non-blocking mode.
+ if (new_stream.disable (ACE_NONBLOCK) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%p\n",
+ "disable"),
+ 0);
+ else if (new_stream.get_remote_addr (cli_addr) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%p\n",
+ "get_remote_addr"),
+ 0);
+
+ ACE_DEBUG ((LM_DEBUG,
+ "(%P|%t) client %s connected from %d\n",
+ cli_addr.get_host_name (),
+ cli_addr.get_port_number ()));
+
+ // Timer business
+ ACE_Profile_Timer timer;
+ timer.start ();
+
+ size_t total_bytes = 0;
+ size_t message_count = 0;
+
+ char *request = 0;
+
+ // Read data from client (terminate on error).
+
+ for (;;)
+ {
+ ACE_INT32 len;
+
+ ssize_t r_bytes = new_stream.recv_n ((void *) &len,
+ sizeof (ACE_INT32));
+ if (r_bytes == -1)
+ {
+ ACE_ERROR ((LM_ERROR,
+ "%p\n",
+ "recv"));
+ break;
+ }
+ else if (r_bytes == 0)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ "(%P|%t) reached end of input, connection closed by client\n"));
+ break;
+ }
+ else if (r_bytes != sizeof (ACE_INT32))
+ {
+ ACE_ERROR ((LM_ERROR,
+ "(%P|%t) %p\n",
+ "recv_n failed"));
+ break;
+ }
+ else
+ {
+ len = ntohl (len);
+ ACE_NEW_RETURN (request,
+ char [len],
+ 0);
+ }
+
+ // Subtract off the sizeof the length prefix.
+ r_bytes = new_stream.recv_n (request,
+ len - sizeof (ACE_UINT32));
+
+ if (r_bytes == -1)
+ {
+ ACE_ERROR ((LM_ERROR,
+ "%p\n",
+ "recv"));
+ break;
+ }
+ else if (r_bytes == 0)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ "(%P|%t) reached end of input, connection closed by client\n"));
+ break;
+ }
+ else if (verbose
+ && ACE::write_n (ACE_STDOUT, request, r_bytes) != r_bytes)
+ ACE_ERROR ((LM_ERROR,
+ "%p\n",
+ "ACE::write_n"));
+
+ total_bytes += size_t (r_bytes);
+ message_count++;
+
+ delete [] request;
+ request = 0;
+ }
+
+ timer.stop ();
+
+ ACE_Profile_Timer::ACE_Elapsed_Time et;
+ timer.elapsed_time (et);
+
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("\t\treal time = %f secs \n\t\tuser time = %f secs \n\t\tsystem time = %f secs\n"),
+ et.real_time,
+ et.user_time,
+ et.system_time));
+
+ double messages_per_sec = double (message_count) / et.real_time;
+
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("\t\tmessages = %d\n\t\ttotal bytes = %d\n\t\tmbits/sec = %f\n\t\tusec-per-message = %f\n\t\tmessages-per-second = %0.00f\n"),
+ message_count,
+ total_bytes,
+ (((double) total_bytes * 8) / et.real_time) / (double) (1024 * 1024),
+ (et.real_time / (double) message_count) * 1000000,
+ messages_per_sec < 0 ? 0 : messages_per_sec));
+
+ // Close new endpoint (listening endpoint stays open).
+ new_stream.close ();
+
+ delete [] request;
+ return 0;
+}
+
+static int
+run_event_loop (u_short port)
+{
+ // Raise the socket handle limit to the maximum.
+ ACE::set_handle_limit ();
+
+ // Create the oneway and twoway acceptors.
+ ACE_SOCK_Acceptor twoway_acceptor;
+ ACE_SOCK_Acceptor oneway_acceptor;
+
+ // Create the oneway and twoway server addresses.
+ ACE_INET_Addr twoway_server_addr (port);
+ ACE_INET_Addr oneway_server_addr (port + 1);
+
+ // Create acceptors, reuse the address.
+ if (twoway_acceptor.open (twoway_server_addr, 1) == -1
+ || oneway_acceptor.open (oneway_server_addr, 1) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%p\n",
+ "open"),
+ 1);
+ // Check to see what addresses we actually got bound to!
+ else if (twoway_acceptor.get_local_addr (twoway_server_addr) == -1
+ || oneway_acceptor.get_local_addr (oneway_server_addr) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%p\n",
+ "get_local_addr"),
+ 1);
+
+ ACE_DEBUG ((LM_DEBUG,
+ "(%P|%t) starting twoway server at port %d and oneway server at port %d\n",
+ twoway_server_addr.get_port_number (),
+ oneway_server_addr.get_port_number ()));
+
+ // Keep these objects out here to prevent excessive constructor
+ // calls within the loop.
+ ACE_SOCK_Stream new_stream;
+
+ ACE_Handle_Set handle_set;
+ handle_set.set_bit (twoway_acceptor.get_handle ());
+ handle_set.set_bit (oneway_acceptor.get_handle ());
+
+ // Performs the iterative server activities.
+
+ for (;;)
+ {
+ ACE_Time_Value timeout (ACE_DEFAULT_TIMEOUT);
+ ACE_Handle_Set temp = handle_set;
+
+ int result = ACE_OS::select (int (oneway_acceptor.get_handle ()) + 1,
+ (fd_set *) temp,
+ 0,
+ 0,
+ timeout);
+ if (result == -1)
+ ACE_ERROR ((LM_ERROR,
+ "(%P|%t) %p\n",
+ "select"));
+ else if (result == 0 && verbose)
+ ACE_DEBUG ((LM_DEBUG,
+ "(%P|%t) select timed out\n"));
+ else
+ {
+ if (temp.is_set (twoway_acceptor.get_handle ()))
+ {
+ if (twoway_acceptor.accept (new_stream) == -1)
+ {
+ ACE_ERROR ((LM_ERROR,
+ "%p\n",
+ "accept"));
+ continue;
+ }
+ else
+ ACE_DEBUG ((LM_DEBUG,
+ "(%P|%t) spawning twoway server\n"));
+
+ // Run the twoway server.
+ run_server (twoway_server,
+ new_stream.get_handle ());
+ }
+ if (temp.is_set (oneway_acceptor.get_handle ()))
+ {
+ if (oneway_acceptor.accept (new_stream) == -1)
+ {
+ ACE_ERROR ((LM_ERROR, "%p\n", "accept"));
+ continue;
+ }
+ else
+ ACE_DEBUG ((LM_DEBUG,
+ "(%P|%t) spawning oneway server\n"));
+
+ // Run the oneway server.
+ run_server (oneway_server,
+ new_stream.get_handle ());
+ }
+ }
+ }
+
+ /* NOTREACHED */
+}
+
+int
+ACE_TMAIN (int argc, ACE_TCHAR *argv[])
+{
+ u_short port = ACE_DEFAULT_SERVER_PORT;
+
+ if (argc > 1)
+ port = ACE_OS::atoi (argv[1]);
+
+ return run_event_loop (port);
+}
diff --git a/ACE/examples/IPC_SAP/SOCK_SAP/CPP-memclient.cpp b/ACE/examples/IPC_SAP/SOCK_SAP/CPP-memclient.cpp
new file mode 100644
index 00000000000..59c4beaa487
--- /dev/null
+++ b/ACE/examples/IPC_SAP/SOCK_SAP/CPP-memclient.cpp
@@ -0,0 +1,53 @@
+// $Id$
+
+// This tests the features of the <ACE_MEM_Connector> and
+// <ACE_MEM_Stream> classes. In addition, it can be used to test the
+// oneway and twoway latency and throughput at the socket-level. This
+// is useful as a baseline to compare against ORB-level performance
+// for the same types of data.
+
+#include "ace/OS_NS_string.h"
+#include "ace/MEM_Connector.h"
+#include "ace/INET_Addr.h"
+#include "ace/Thread_Manager.h"
+#include "ace/Singleton.h"
+#include "ace/Get_Opt.h"
+#include "ace/High_Res_Timer.h"
+
+
+ACE_RCSID(SOCK_SAP, CPP_inclient, "$Id$")
+
+static int
+run_client (void)
+{
+ ACE_MEM_Connector connector;
+ ACE_MEM_Stream stream;
+ ACE_MEM_Addr server_addr (ACE_DEFAULT_SERVER_PORT);
+
+ if (connector.connect (stream, server_addr.get_remote_addr ()) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("%p\n"),
+ ACE_TEXT ("connect")), -1);
+
+ char buf [MAXPATHLEN];
+ while (fgets (buf, MAXPATHLEN, stdin) >0)
+ {
+ stream.send (buf, ACE_OS::strlen (buf)+1);
+ stream.recv (buf, MAXPATHLEN);
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Echo: %C\n"), buf));
+ }
+
+ return 0;
+}
+
+int ACE_TMAIN (int argc, ACE_TCHAR *argv[])
+{
+ ACE_UNUSED_ARG(argc);
+ // Initialize the logger.
+ ACE_LOG_MSG->open (argv[0]);
+
+ // Run the client
+ run_client ();
+
+ return 0;
+}
+
diff --git a/ACE/examples/IPC_SAP/SOCK_SAP/CPP-memserver.cpp b/ACE/examples/IPC_SAP/SOCK_SAP/CPP-memserver.cpp
new file mode 100644
index 00000000000..4ef76e51b38
--- /dev/null
+++ b/ACE/examples/IPC_SAP/SOCK_SAP/CPP-memserver.cpp
@@ -0,0 +1,70 @@
+// $Id$
+
+// This example tests the features of the <ACE_MEM_Acceptor>,
+// <ACE_MEM_Stream>, and <ACE_Svc_Handler> classes. If the platform
+// supports threads it uses a thread-per-connection concurrency model.
+// Otherwise, it uses a single-threaded iterative server model.
+
+#include "ace/MEM_Acceptor.h"
+#include "ace/Thread_Manager.h"
+#include "ace/Handle_Set.h"
+#include "ace/Profile_Timer.h"
+
+ACE_RCSID(SOCK_SAP, CPP_inserver, "$Id$")
+
+static int
+run_event_loop (u_short port)
+{
+ // Create the acceptors.
+ ACE_MEM_Acceptor acceptor;
+
+ ACE_MEM_Addr server_addr (port);
+
+ // Create acceptors, reuse the address.
+ if (acceptor.open (server_addr, 1) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%p\n",
+ "open"),
+ 1);
+ else if (acceptor.get_local_addr (server_addr) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%p\n",
+ "get_local_addr"),
+ 1);
+
+ ACE_DEBUG ((LM_DEBUG,
+ "(%P|%t) starting server at port %d\n",
+ server_addr.get_port_number ()));
+
+ // Keep these objects out here to prevent excessive constructor
+ // calls within the loop.
+ ACE_MEM_Stream new_stream;
+
+ // blocking wait on accept.
+ if (acceptor.accept (new_stream) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%p\n",
+ "accept"),
+ -1);
+
+ char buf[MAXPATHLEN];
+ int len = 0;
+ while ((len = new_stream.recv (buf, MAXPATHLEN)) != -1)
+ {
+ ACE_DEBUG ((LM_DEBUG, "%s\n", buf));
+ new_stream.send (buf, len);
+ }
+
+ return new_stream.fini ();
+}
+
+int
+ACE_TMAIN (int argc, ACE_TCHAR *argv[])
+{
+ u_short port = ACE_DEFAULT_SERVER_PORT;
+
+ if (argc > 1)
+ port = ACE_OS::atoi (argv[1]);
+
+ return run_event_loop (port);
+}
diff --git a/ACE/examples/IPC_SAP/SOCK_SAP/CPP-unclient.cpp b/ACE/examples/IPC_SAP/SOCK_SAP/CPP-unclient.cpp
new file mode 100644
index 00000000000..9f3fdec22b9
--- /dev/null
+++ b/ACE/examples/IPC_SAP/SOCK_SAP/CPP-unclient.cpp
@@ -0,0 +1,71 @@
+// $Id$
+
+// ACE_LSOCK Client.
+
+#include "ace/LSOCK_Connector.h"
+#include "ace/UNIX_Addr.h"
+#include "ace/Log_Msg.h"
+#include "ace/OS_main.h"
+#include "ace/OS_NS_unistd.h"
+
+ACE_RCSID(SOCK_SAP, CPP_unclient, "$Id$")
+
+#if !defined (ACE_LACKS_UNIX_DOMAIN_SOCKETS)
+int
+ACE_TMAIN (int argc, ACE_TCHAR *argv[])
+{
+ const ACE_TCHAR *rendezvous = argc > 1 ? argv[1] : ACE_DEFAULT_RENDEZVOUS;
+ char buf[BUFSIZ];
+
+ ACE_LSOCK_Stream cli_stream;
+ ACE_LSOCK_Connector con;
+ ACE_UNIX_Addr remote_addr (rendezvous);
+
+ // Establish the connection with server.
+ if (con.connect (cli_stream, remote_addr) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("connect")),
+ 1);
+
+ // Send data to server (correctly handles "incomplete writes").
+
+ for (int r_bytes;
+ (r_bytes = ACE_OS::read (ACE_STDIN, buf, sizeof buf)) > 0;
+ )
+ if (cli_stream.send_n (buf, r_bytes) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("send_n")),
+ 1);
+
+ // Explicitly close the writer-side of the connection.
+ if (cli_stream.close_writer () == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("close_writer")),
+ 1);
+
+ // Wait for handshake with server.
+ if (cli_stream.recv_n (buf, 1) != 1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("recv_n")),
+ 1);
+
+ // Close the connection completely.
+ if (cli_stream.close () == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("close")),
+ 1);
+ return 0;
+}
+#else
+int
+ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "this platform does not support UNIX-domain sockets\n"), -1);
+}
+#endif /* ACE_LACKS_UNIX_DOMAIN_SOCKETS */
diff --git a/ACE/examples/IPC_SAP/SOCK_SAP/CPP-unserver.cpp b/ACE/examples/IPC_SAP/SOCK_SAP/CPP-unserver.cpp
new file mode 100644
index 00000000000..cddfe787d92
--- /dev/null
+++ b/ACE/examples/IPC_SAP/SOCK_SAP/CPP-unserver.cpp
@@ -0,0 +1,159 @@
+// $Id$
+
+// This example tests the features of the ACE_LSOCK_Acceptor and
+// ACE_LSOCK_Stream classes. If the platform supports threads it uses
+// a thread-per-request concurrency model.
+
+#include "ace/LSOCK_Acceptor.h"
+#include "ace/Thread_Manager.h"
+#include "ace/OS_main.h"
+#include "ace/OS_NS_unistd.h"
+
+ACE_RCSID(SOCK_SAP, CPP_unserver, "$Id$")
+
+#if !defined (ACE_LACKS_UNIX_DOMAIN_SOCKETS)
+
+// Are we running verbosely?
+static int verbose = 1;
+
+// Entry point into the server task.
+
+static void *
+server (void *arg)
+{
+ ACE_UNIX_Addr cli_addr;
+ ACE_LSOCK_Stream new_stream;
+ ACE_HANDLE handle = (ACE_HANDLE) (long) arg;
+
+ new_stream.set_handle (handle);
+
+ // Make sure we're not in non-blocking mode.
+ if (new_stream.disable (ACE_NONBLOCK) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("disable")),
+ 0);
+
+ if (new_stream.get_remote_addr (cli_addr) == -1)
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("get_remote_addr")));
+
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("(%P|%t) client connected from %C\n"),
+ cli_addr.get_path_name ()));
+
+ // Read data from client (terminate on error).
+
+ for (;;)
+ {
+ char buf[BUFSIZ];
+
+ ssize_t r_bytes = new_stream.recv (buf, sizeof buf);
+
+ if (r_bytes == -1)
+ {
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("recv")));
+ break;
+
+ }
+ else if (r_bytes == 0)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("(%P|%t) reached end of input, connection closed by client\n")));
+ break;
+ }
+ else if (verbose && ACE::write_n (ACE_STDOUT, buf, r_bytes) != r_bytes)
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("ACE::write_n")));
+ else if (new_stream.send_n (buf, r_bytes) != r_bytes)
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("send_n")));
+ }
+
+ // Close new endpoint (listening endpoint stays open).
+ if (new_stream.close () == -1)
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("close")));
+
+ return 0;
+}
+
+static int
+run_event_loop (const ACE_TCHAR rendezvous[])
+{
+ ACE_LSOCK_Acceptor peer_acceptor;
+
+ // Create a server address.
+ ACE_UNIX_Addr server_addr (rendezvous);
+
+ ACE_OS::unlink (rendezvous);
+
+ // Create a server.
+
+ if (peer_acceptor.open (server_addr) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("open")),
+ 1);
+ else if (peer_acceptor.get_local_addr (server_addr) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("get_local_addr")),
+ -1);
+
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("starting server %C\n"),
+ server_addr.get_path_name ()));
+
+ // Keep these guys out here to prevent excessive constructor
+ // calls...
+ ACE_LSOCK_Stream new_stream;
+
+ // Performs the iterative server activities.
+
+ for (;;)
+ {
+ ACE_Time_Value timeout (ACE_DEFAULT_TIMEOUT);
+
+ if (peer_acceptor.accept (new_stream, 0, &timeout) == -1)
+ {
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("accept")));
+ continue;
+ }
+
+#if defined (ACE_HAS_THREADS)
+ if (ACE_Thread_Manager::instance ()->spawn ((ACE_THR_FUNC) server,
+ reinterpret_cast<void *> (new_stream.get_handle ()),
+ THR_DETACHED) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("(%P|%t) %p\n"),
+ ACE_TEXT ("spawn")),
+ 1);
+#else
+ server (reinterpret_cast<void *> (new_stream.get_handle ()));
+#endif /* ACE_HAS_THREADS */
+ }
+
+ ACE_NOTREACHED (return 0;)
+}
+
+int
+ACE_TMAIN (int argc, ACE_TCHAR *argv[])
+{
+ return run_event_loop (argc > 1 ? argv[1] : ACE_DEFAULT_RENDEZVOUS);
+}
+#else
+int ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "this platform does not support UNIX-domain sockets\n"), -1);
+}
+#endif /* ACE_LACKS_UNIX_DOMAIN_SOCKETS */
diff --git a/ACE/examples/IPC_SAP/SOCK_SAP/FD-unclient.cpp b/ACE/examples/IPC_SAP/SOCK_SAP/FD-unclient.cpp
new file mode 100644
index 00000000000..1c21aeb74c0
--- /dev/null
+++ b/ACE/examples/IPC_SAP/SOCK_SAP/FD-unclient.cpp
@@ -0,0 +1,60 @@
+// $Id$
+
+#include "ace/OS_NS_fcntl.h"
+#include "ace/LSOCK_Connector.h"
+#include "ace/UNIX_Addr.h"
+#include "ace/Log_Msg.h"
+#include "ace/OS_main.h"
+
+ACE_RCSID(SOCK_SAP, FD_unclient, "$Id$")
+
+#if defined (ACE_HAS_MSG) && !defined (ACE_LACKS_UNIX_DOMAIN_SOCKETS)
+// ACE_LSOCK Client.
+
+int
+ACE_TMAIN (int argc, ACE_TCHAR *argv[])
+{
+ const ACE_TCHAR *file_name = argc > 1 ? argv[1] : ACE_TEXT ("./local_data");
+ const ACE_TCHAR *rendezvous = argc > 2 ? argv[2] : ACE_DEFAULT_RENDEZVOUS;
+
+ ACE_LSOCK_Stream cli_stream;
+ ACE_UNIX_Addr addr (rendezvous);
+
+ // Establish the connection with server.
+ ACE_LSOCK_Connector connector;
+
+ if (connector.connect (cli_stream, addr) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("%p"), ACE_TEXT ("connect")), -1);
+
+ ACE_HANDLE handle = ACE_OS::open (file_name, O_RDONLY);
+
+ if (handle == ACE_INVALID_HANDLE)
+ ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("%p"), ACE_TEXT ("open")), -1);
+
+ // Send handle to server (correctly handles incomplete writes).
+ if (cli_stream.send_handle (handle) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("%p"), ACE_TEXT ("send")), -1);
+
+ char buf[BUFSIZ];
+ ssize_t n = cli_stream.recv (buf, sizeof buf);
+
+ if (n == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("%p"), ACE_TEXT ("recv")), -1);
+ else if (n == 0)
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("server shutdown (bug in kernel?)\n")));
+ else
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("server %*C shutdown\n"), n, buf));
+
+ // Explicitly close the connection.
+ if (cli_stream.close () == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("%p"), ACE_TEXT ("close")), -1);
+
+ return 0;
+}
+#else
+int ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("your platform must support sendmsg/recvmsg to run this test\n")), -1);
+}
+#endif /* ACE_HAS_MSG */
diff --git a/ACE/examples/IPC_SAP/SOCK_SAP/FD-unserver.cpp b/ACE/examples/IPC_SAP/SOCK_SAP/FD-unserver.cpp
new file mode 100644
index 00000000000..b629b9f0dd8
--- /dev/null
+++ b/ACE/examples/IPC_SAP/SOCK_SAP/FD-unserver.cpp
@@ -0,0 +1,100 @@
+// $Id$
+
+#include "ace/LSOCK_Acceptor.h"
+#include "ace/LSOCK_Stream.h"
+#include "ace/UNIX_Addr.h"
+#include "ace/Log_Msg.h"
+#include "ace/OS_main.h"
+#include "ace/OS_NS_string.h"
+#include "ace/OS_NS_stdio.h"
+#include "ace/OS_NS_unistd.h"
+#include "ace/OS_NS_stdlib.h"
+
+ACE_RCSID(SOCK_SAP, FD_unserver, "$Id$")
+
+#if !defined (ACE_LACKS_UNIX_DOMAIN_SOCKETS)
+
+// ACE_LSOCK Server
+
+void
+handle_client (ACE_LSOCK_Stream &stream)
+{
+ char buf[BUFSIZ];
+ ACE_HANDLE handle;
+
+ // Retrieve the socket descriptor passed from the client.
+
+ if (stream.recv_handle (handle) == -1)
+ ACE_ERROR ((LM_ERROR, "%p", "recv_handle"));
+
+ ACE_DEBUG ((LM_DEBUG, "(%P|%t) ----------------------------------------\n"));
+
+ // Read data from client (correctly handles incomplete reads due to
+ // flow control).
+
+ for (ssize_t n;
+ (n = ACE_OS::read (handle, buf, sizeof buf)) > 0;
+ )
+ ACE_DEBUG ((LM_DEBUG, "%*s", n, buf));
+
+ ACE_OS::sprintf (buf, "%d", static_cast<int> (ACE_OS::getpid ()));
+
+ ACE_DEBUG ((LM_DEBUG, "(%s, %d) ----------------------------------------\n", buf, ACE_OS::strlen (buf)));
+
+ // Tell the client to shut down.
+ if (stream.send_n (buf, ACE_OS::strlen (buf)) == -1)
+ ACE_ERROR ((LM_ERROR, "%p", "send"));
+
+ // Close new endpoint (listening endpoint stays open).
+ if (stream.close () == -1)
+ ACE_ERROR ((LM_ERROR, "%p", "close"));
+}
+
+int
+ACE_TMAIN (int argc, ACE_TCHAR *argv[])
+{
+ const ACE_TCHAR *rendezvous = argc > 1 ? argv[1] : ACE_DEFAULT_RENDEZVOUS;
+ // Create a server.
+ ACE_OS::unlink (rendezvous);
+ ACE_UNIX_Addr addr (rendezvous);
+ ACE_LSOCK_Acceptor peer_acceptor (addr);
+ ACE_LSOCK_Stream stream;
+
+ // Performs the concurrent server activities.
+
+ for (;;)
+ {
+ // Create a new ACE_SOCK_Stream endpoint.
+ if (peer_acceptor.accept (stream) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, "(%P|%t) %p\n", "accept"), -1);
+
+ ACE_DEBUG ((LM_DEBUG, "(%P|%t) accepted new connection\n"));
+
+#if defined (VXWORKS)
+ handle_client (stream);
+#else
+ switch (ACE_OS::fork (argv[0]))
+ {
+ case -1:
+ ACE_ERROR_RETURN ((LM_ERROR, "(%P|%t) %p\n", "fork"), -1);
+ /* NOTREACHED */
+ case 0:
+ ACE_LOG_MSG->sync (argv[0]);
+ handle_client (stream);
+ ACE_OS::exit (0);
+ /* NOTREACHED */
+ default:
+ stream.close ();
+ }
+#endif /* VXWORKS */
+ }
+
+ ACE_NOTREACHED (return 0;)
+}
+#else
+int
+ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ ACE_ERROR_RETURN ((LM_ERROR, "your platform doesn't not support UNIX domain sockets\n"), -1);
+}
+#endif /* ACE_LACKS_UNIX_DOMAIN_SOCKETS */
diff --git a/ACE/examples/IPC_SAP/SOCK_SAP/Makefile.am b/ACE/examples/IPC_SAP/SOCK_SAP/Makefile.am
new file mode 100644
index 00000000000..50260dc7343
--- /dev/null
+++ b/ACE/examples/IPC_SAP/SOCK_SAP/Makefile.am
@@ -0,0 +1,179 @@
+## Process this file with automake to create Makefile.in
+##
+## $Id$
+##
+## This file was generated by MPC. Any changes made directly to
+## this file will be lost the next time it is generated.
+##
+## MPC Command:
+## /acebuilds/ACE_wrappers-repository/bin/mwc.pl -include /acebuilds/MPC/config -include /acebuilds/MPC/templates -feature_file /acebuilds/ACE_wrappers-repository/local.features -noreldefs -type automake -exclude build,Kokyu
+
+ACE_BUILDDIR = $(top_builddir)
+ACE_ROOT = $(top_srcdir)
+
+
+## Makefile.Sock_Sap_CPP_Inclient.am
+noinst_PROGRAMS = CPP-inclient
+
+CPP_inclient_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+CPP_inclient_SOURCES = \
+ CPP-inclient.cpp \
+ CPP-inclient.h
+
+CPP_inclient_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Makefile.Sock_Sap_CPP_Inserver.am
+
+if !BUILD_ACE_FOR_TAO
+noinst_PROGRAMS += CPP-inserver
+
+CPP_inserver_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+CPP_inserver_SOURCES = \
+ CPP-inserver.cpp \
+ CPP-inclient.h \
+ CPP-inserver-fancy.h
+
+CPP_inserver_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+endif !BUILD_ACE_FOR_TAO
+
+## Makefile.Sock_Sap_CPP_Memclient.am
+
+if !BUILD_ACE_FOR_TAO
+noinst_PROGRAMS += CPP-memclient
+
+CPP_memclient_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+CPP_memclient_SOURCES = \
+ CPP-memclient.cpp \
+ CPP-inclient.h \
+ CPP-inserver-fancy.h
+
+CPP_memclient_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+endif !BUILD_ACE_FOR_TAO
+
+## Makefile.Sock_Sap_CPP_Memserver.am
+
+if !BUILD_ACE_FOR_TAO
+noinst_PROGRAMS += CPP-memserver
+
+CPP_memserver_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+CPP_memserver_SOURCES = \
+ CPP-memserver.cpp \
+ CPP-inclient.h \
+ CPP-inserver-fancy.h
+
+CPP_memserver_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+endif !BUILD_ACE_FOR_TAO
+
+## Makefile.Sock_Sap_CPP_Unclient.am
+
+if !BUILD_ACE_FOR_TAO
+noinst_PROGRAMS += CPP-unclient
+
+CPP_unclient_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+CPP_unclient_SOURCES = \
+ CPP-unclient.cpp \
+ CPP-inclient.h \
+ CPP-inserver-fancy.h
+
+CPP_unclient_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+endif !BUILD_ACE_FOR_TAO
+
+## Makefile.Sock_Sap_CPP_Unserver.am
+
+if !BUILD_ACE_FOR_TAO
+noinst_PROGRAMS += CPP-unserver
+
+CPP_unserver_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+CPP_unserver_SOURCES = \
+ CPP-unserver.cpp \
+ CPP-inclient.h \
+ CPP-inserver-fancy.h
+
+CPP_unserver_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+endif !BUILD_ACE_FOR_TAO
+
+## Makefile.Sock_Sap_C_Inclient.am
+noinst_PROGRAMS += C-inclient
+
+C_inclient_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+C_inclient_SOURCES = \
+ C-inclient.cpp \
+ CPP-inclient.h \
+ CPP-inserver-fancy.h
+
+C_inclient_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Makefile.Sock_Sap_C_Inserver.am
+noinst_PROGRAMS += C-inserver
+
+C_inserver_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+C_inserver_SOURCES = \
+ C-inserver.cpp \
+ CPP-inclient.h \
+ CPP-inserver-fancy.h
+
+C_inserver_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Makefile.Sock_Sap_FD_Unclient.am
+
+if !BUILD_ACE_FOR_TAO
+noinst_PROGRAMS += FD-unclient
+
+FD_unclient_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+FD_unclient_SOURCES = \
+ FD-unclient.cpp \
+ CPP-inclient.h \
+ CPP-inserver-fancy.h
+
+FD_unclient_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+endif !BUILD_ACE_FOR_TAO
+
+## Clean up template repositories, etc.
+clean-local:
+ -rm -f *~ *.bak *.rpo *.sym lib*.*_pure_* core core.*
+ -rm -f gcctemp.c gcctemp so_locations *.ics
+ -rm -rf cxx_repository ptrepository ti_files
+ -rm -rf templateregistry ir.out
+ -rm -rf ptrepository SunWS_cache Templates.DB
diff --git a/ACE/examples/IPC_SAP/SOCK_SAP/README b/ACE/examples/IPC_SAP/SOCK_SAP/README
new file mode 100644
index 00000000000..bbe0f20ce5a
--- /dev/null
+++ b/ACE/examples/IPC_SAP/SOCK_SAP/README
@@ -0,0 +1,46 @@
+This directory contains groups of client and server test programs that
+exercise the various C++ wrappers for sockets. In general, the test
+programs do more or less the same thing -- the client establishes a
+connection with the server and then transfers data to the server,
+which keeps printing the data until EOF is reached (e.g., user types
+^D).
+
+Unless noted differently, the server is implemented as an "iterative
+server," i.e., it only deals with one client at a time. The following
+describes each set of tests in more detail:
+
+ . C-{inclient,inserver}.cpp -- This is basically a C code
+ implementation that opens a connection to the server and
+ sends all the data from the stdin using Internet domain
+ sockets (i.e., TCP).
+
+ . CPP-{inclient,inserver}.cpp -- This test is
+ a more sophisticated C++ wrapper version of the preceeding
+ "C" test using Internet domain sockets (i.e., TCP).
+ It allows you to test oneway and twoway socket communication
+ latency and throughput between two processes on the same
+ machine or on different machines.
+
+ . CPP-inserver-fancy.cpp -- This program is a more glitzy
+ version of CPP-inserver.cpp that illustrates additional
+ features of ACE, such as ACE_Svc_Handler.
+
+ . CPP-inserver-poll.cpp -- This test illustrates how to
+ write single-threaded concurrent servers using UNIX SVR4
+ poll(). You can run this test using the CPP-inclient.cpp
+ program as the oneway client.
+
+ . CPP-{unclient,unserver}.cpp -- This test is basically
+ a C++ wrapper version of the preceeding "C++" test using
+ UNIX domain sockets. Note that this test only works
+ between a client and server process on the same machine.
+
+ . FD-{unclient,inclient}.cpp -- This test illustrates
+ how to pass file descriptors between a client and a
+ concurrent server process on the same machine using the ACE
+ C++ wrappers for UNIX domain sockets.
+
+For examples of the ACE SOCK_{Dgram,CODgram} and
+SOCK_Dgram_{Mcast,Bcast} wrappers, please take a look in the
+./examples/Reactor/{Dgram,Multicast,Ntalker} directories.
+
diff --git a/ACE/examples/IPC_SAP/SOCK_SAP/local_data b/ACE/examples/IPC_SAP/SOCK_SAP/local_data
new file mode 100644
index 00000000000..c0119859a28
--- /dev/null
+++ b/ACE/examples/IPC_SAP/SOCK_SAP/local_data
@@ -0,0 +1 @@
+I am Iron man!
diff --git a/ACE/examples/IPC_SAP/SOCK_SAP/run_test b/ACE/examples/IPC_SAP/SOCK_SAP/run_test
new file mode 100755
index 00000000000..7f0a4dbdaa7
--- /dev/null
+++ b/ACE/examples/IPC_SAP/SOCK_SAP/run_test
@@ -0,0 +1,36 @@
+#! /bin/sh
+# $Id$
+#
+# Spawns CPP-inserver-fancy and CPP-inclient executables on a single host.
+
+usage="usage: $0 #client_threads"
+
+user=`whoami`
+iterations=1000
+
+if [ $# -ne 1 ]; then
+ echo $usage;
+ exit 1
+fi
+threads=$1;
+
+
+########
+######## Enable signal handler.
+########
+trap 'kill -1 $server_pid; ' 0 1 2 15
+
+
+########
+######## Start CPP-inserver-fancy and save its pid.
+########
+./CPP-inserver-fancy > \
+ ${tmp}server.log 2>&1 &
+server_pid=$!
+
+sleep 2;
+
+########
+######## Start CPP-inclient.
+########
+./CPP-inclient -2 -T 100000 -m 69 -t $threads -i 100 > ${tmp}client-${threads}.log 2>&1
diff --git a/ACE/examples/IPC_SAP/SOCK_SAP/sock_sap.mpc b/ACE/examples/IPC_SAP/SOCK_SAP/sock_sap.mpc
new file mode 100644
index 00000000000..814280a515c
--- /dev/null
+++ b/ACE/examples/IPC_SAP/SOCK_SAP/sock_sap.mpc
@@ -0,0 +1,72 @@
+// -*- MPC -*-
+// $Id$
+
+project(*C_inclient) : aceexe {
+ exename = C-inclient
+ Source_Files {
+ C-inclient.cpp
+ }
+}
+
+project(*C_inserver) : aceexe {
+ exename = C-inserver
+ Source_Files {
+ C-inserver.cpp
+ }
+}
+
+project(*CPP_inclient) : aceexe {
+ exename = CPP-inclient
+ Source_Files {
+ CPP-inclient.cpp
+ }
+}
+
+project(*CPP_inserver) : aceexe {
+ avoids += ace_for_tao
+ exename = CPP-inserver
+ Source_Files {
+ CPP-inserver.cpp
+ }
+}
+
+project(*CPP_memclient) : aceexe {
+ avoids += ace_for_tao
+ exename = CPP-memclient
+ Source_Files {
+ CPP-memclient.cpp
+ }
+}
+
+project(*CPP_memserver) : aceexe {
+ avoids += ace_for_tao
+ exename = CPP-memserver
+ Source_Files {
+ CPP-memserver.cpp
+ }
+}
+
+project(*FD_unclient) : aceexe {
+ avoids += ace_for_tao
+ exename = FD-unclient
+ Source_Files {
+ FD-unclient.cpp
+ }
+}
+
+project(*CPP_unclient) : aceexe {
+ avoids += ace_for_tao
+ exename = CPP-unclient
+ Source_Files {
+ CPP-unclient.cpp
+ }
+}
+
+project(*CPP_unserver) : aceexe {
+ avoids += ace_for_tao
+ exename = CPP-unserver
+ Source_Files {
+ CPP-unserver.cpp
+ }
+}
+
diff --git a/ACE/examples/IPC_SAP/SOCK_SAP/summarize b/ACE/examples/IPC_SAP/SOCK_SAP/summarize
new file mode 100755
index 00000000000..ee8ffd2df25
--- /dev/null
+++ b/ACE/examples/IPC_SAP/SOCK_SAP/summarize
@@ -0,0 +1,45 @@
+eval '(exit $?0)' && eval 'exec perl -w -S $0 ${1+"$@"}'
+ & eval 'exec perl -w -S $0 $argv:q'
+ if 0;
+
+# $Id$
+#
+# Summarizes results from a series of runs of run_test, with
+# different numbers of clients. Example usage:
+#
+# $ for i in 1 2 5 10 15 20 25 30 35 40 45 50; do ./run_test $i; done
+# $ ./summarize
+#
+# The first three lines above let this script run without specifying the
+# full path to perl, as long as it is in the user's PATH.
+# Taken from perlrun man page.
+
+@files = glob 'client-*.log';
+@total_threads = ();
+
+foreach $file (@files) {
+ my ($i);
+ ($i = $file) =~ s/client-(\d+).log/$1/;
+ push @total_threads, $i;
+}
+
+print "No.of threads\t\tAverage Latency\n\n";
+
+foreach $total_threads (sort {$a <=> $b} @total_threads) {
+ undef $high_latency;
+
+ $high_latency = 0;
+ open (FILE, "client-${total_threads}.log") ||
+ die "$0: unable to open \"client-${total_threads}.log\"\n";
+ while ($line = <FILE>) {
+ if ($line =~ /.*usec-per-message = ([\d\.]+)/)
+ {
+ $high_latency += $1 ;
+ $number++;
+ }
+ }
+ close FILE;
+
+ printf "%3d\t\t\t%8f\n",
+ $total_threads, $high_latency/$number;
+}
diff --git a/ACE/examples/IPC_SAP/SPIPE_SAP/.cvsignore b/ACE/examples/IPC_SAP/SPIPE_SAP/.cvsignore
new file mode 100644
index 00000000000..46bf34bbdfd
--- /dev/null
+++ b/ACE/examples/IPC_SAP/SPIPE_SAP/.cvsignore
@@ -0,0 +1,16 @@
+NPClient
+NPClient
+NPServer
+NPServer
+client
+client
+consumer_msg
+consumer_msg
+consumer_read
+consumer_read
+producer_msg
+producer_msg
+producer_read
+producer_read
+server
+server
diff --git a/ACE/examples/IPC_SAP/SPIPE_SAP/Makefile.am b/ACE/examples/IPC_SAP/SPIPE_SAP/Makefile.am
new file mode 100644
index 00000000000..662c99fc452
--- /dev/null
+++ b/ACE/examples/IPC_SAP/SPIPE_SAP/Makefile.am
@@ -0,0 +1,132 @@
+## Process this file with automake to create Makefile.in
+##
+## $Id$
+##
+## This file was generated by MPC. Any changes made directly to
+## this file will be lost the next time it is generated.
+##
+## MPC Command:
+## /acebuilds/ACE_wrappers-repository/bin/mwc.pl -include /acebuilds/MPC/config -include /acebuilds/MPC/templates -feature_file /acebuilds/ACE_wrappers-repository/local.features -noreldefs -type automake -exclude build,Kokyu
+
+ACE_BUILDDIR = $(top_builddir)
+ACE_ROOT = $(top_srcdir)
+
+## Makefile.SPIPE_SAP_Client.am
+noinst_PROGRAMS = client
+
+client_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+client_SOURCES = \
+ client.cpp \
+ shared.h
+
+client_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Makefile.SPIPE_SAP_Consumer_Msg.am
+noinst_PROGRAMS += consumer_msg
+
+consumer_msg_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+consumer_msg_SOURCES = \
+ consumer_msg.cpp \
+ shared.h
+
+consumer_msg_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Makefile.SPIPE_SAP_Consumer_Read.am
+noinst_PROGRAMS += consumer_read
+
+consumer_read_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+consumer_read_SOURCES = \
+ consumer_read.cpp \
+ shared.h
+
+consumer_read_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Makefile.SPIPE_SAP_NPClient.am
+noinst_PROGRAMS += NPClient
+
+NPClient_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+NPClient_SOURCES = \
+ NPClient.cpp \
+ shared.h
+
+NPClient_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Makefile.SPIPE_SAP_NPServer.am
+noinst_PROGRAMS += NPServer
+
+NPServer_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+NPServer_SOURCES = \
+ NPServer.cpp \
+ shared.h
+
+NPServer_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Makefile.SPIPE_SAP_Producer_Msg.am
+noinst_PROGRAMS += producer_msg
+
+producer_msg_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+producer_msg_SOURCES = \
+ producer_msg.cpp \
+ shared.h
+
+producer_msg_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Makefile.SPIPE_SAP_Producer_Read.am
+noinst_PROGRAMS += producer_read
+
+producer_read_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+producer_read_SOURCES = \
+ producer_read.cpp \
+ shared.h
+
+producer_read_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Makefile.SPIPE_SAP_Server.am
+noinst_PROGRAMS += server
+
+server_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+server_SOURCES = \
+ server.cpp \
+ shared.h
+
+server_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Clean up template repositories, etc.
+clean-local:
+ -rm -f *~ *.bak *.rpo *.sym lib*.*_pure_* core core.*
+ -rm -f gcctemp.c gcctemp so_locations *.ics
+ -rm -rf cxx_repository ptrepository ti_files
+ -rm -rf templateregistry ir.out
+ -rm -rf ptrepository SunWS_cache Templates.DB
diff --git a/ACE/examples/IPC_SAP/SPIPE_SAP/NPClient.cpp b/ACE/examples/IPC_SAP/SPIPE_SAP/NPClient.cpp
new file mode 100644
index 00000000000..e7c6c5904aa
--- /dev/null
+++ b/ACE/examples/IPC_SAP/SPIPE_SAP/NPClient.cpp
@@ -0,0 +1,62 @@
+// $Id$
+
+#include "ace/OS_main.h"
+#include "ace/SPIPE_Addr.h"
+#include "ace/SPIPE_Connector.h"
+#include "ace/Log_Msg.h"
+#include "ace/OS_NS_string.h"
+#include "ace/OS_NS_stdlib.h"
+#include "ace/OS_Memory.h"
+
+ACE_RCSID(SPIPE_SAP, NPClient, "$Id$")
+
+#if defined (ACE_WIN32)
+#define MAKE_PIPE_NAME(X) ACE_TEXT ("\\\\.\\pipe\\") ACE_TEXT (X)
+#else
+#define MAKE_PIPE_NAME(X) ACE_TEXT (X)
+#endif
+
+const int DEFAULT_SIZE = 8;
+const int DEFAULT_COUNT = 10000;
+
+int
+ACE_TMAIN (int argc, ACE_TCHAR *argv[])
+{
+ int size = argc > 1 ? ACE_OS::atoi (argv[1]) : DEFAULT_SIZE;
+ int iterations = argc > 2 ? ACE_OS::atoi (argv[2]) : DEFAULT_COUNT;
+ char *buf;
+
+ ACE_NEW_RETURN (buf,
+ char[size],
+ 1);
+
+ const ACE_TCHAR *rendezvous = MAKE_PIPE_NAME ("acepipe");
+
+ ACE_SPIPE_Stream cli_stream;
+ ACE_SPIPE_Connector con;
+ int i;
+
+ if (con.connect (cli_stream,
+ ACE_SPIPE_Addr (rendezvous)) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ rendezvous),
+ -1);
+
+ ACE_OS::strcpy (buf, "hello");
+ size = ACE_OS::strlen (buf) + 1;
+
+ for (i = 0; i < iterations; i++)
+ if (cli_stream.send (buf, size) != size)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("putmsg")),
+ -1);
+
+ if (cli_stream.close () == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("close")),
+ -1);
+ return 0;
+}
diff --git a/ACE/examples/IPC_SAP/SPIPE_SAP/NPServer.cpp b/ACE/examples/IPC_SAP/SPIPE_SAP/NPServer.cpp
new file mode 100644
index 00000000000..4055a2cc02d
--- /dev/null
+++ b/ACE/examples/IPC_SAP/SPIPE_SAP/NPServer.cpp
@@ -0,0 +1,67 @@
+// $Id$
+
+#include "ace/SPIPE_Addr.h"
+#include "ace/SPIPE_Acceptor.h"
+#include "ace/Log_Msg.h"
+#include "ace/OS_NS_stdio.h"
+#include "ace/OS_NS_unistd.h"
+
+ACE_RCSID(SPIPE_SAP, NPServer, "$Id$")
+
+#if defined (ACE_WIN32)
+#define MAKE_PIPE_NAME(X) ACE_TEXT ("\\\\.\\pipe\\") ACE_TEXT (X)
+#else
+#define MAKE_PIPE_NAME(X) ACE_TEXT (X)
+#endif
+
+int
+ACE_TMAIN (int /* argc */, ACE_TCHAR * /* argv */ [])
+{
+ ACE_SPIPE_Acceptor acceptor;
+ ACE_SPIPE_Stream new_stream;
+ char buf[BUFSIZ];
+ int n;
+ const ACE_TCHAR *rendezvous = MAKE_PIPE_NAME ("acepipe");
+
+ // Initialize named pipe listener.
+
+ if (acceptor.open (ACE_SPIPE_Addr (rendezvous)) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("open")), 1);
+
+ for (;;)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("waiting for connection\n")));
+
+ // Accept a client connection.
+ if (acceptor.accept (new_stream, 0) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("accept")),
+ 1);
+
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("Accepted connection\n")));
+
+ while ((n = new_stream.recv (buf, sizeof buf)) > 0)
+ {
+ ACE_OS::fprintf (stderr,
+ "%s\n",
+ buf);
+ ACE_OS::write (ACE_STDOUT,
+ buf,
+ n);
+ }
+
+ if (n == -1)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("End of connection. Closing handle\n")));
+ new_stream.close ();
+ }
+ }
+
+ ACE_NOTREACHED(return 0);
+}
diff --git a/ACE/examples/IPC_SAP/SPIPE_SAP/SPIPE_SAP.mpc b/ACE/examples/IPC_SAP/SPIPE_SAP/SPIPE_SAP.mpc
new file mode 100644
index 00000000000..3f0d7318b3e
--- /dev/null
+++ b/ACE/examples/IPC_SAP/SPIPE_SAP/SPIPE_SAP.mpc
@@ -0,0 +1,58 @@
+// -*- MPC -*-
+// $Id$
+
+project(*client) : aceexe {
+ exename = client
+ Source_Files {
+ client.cpp
+ }
+}
+
+project(*consumer_msg) : aceexe {
+ exename = consumer_msg
+ Source_Files {
+ consumer_msg.cpp
+ }
+}
+
+project(*consumer_read) : aceexe {
+ exename = consumer_read
+ Source_Files {
+ consumer_read.cpp
+ }
+}
+
+project(*NPClient) : aceexe {
+ exename = NPClient
+ Source_Files {
+ NPClient.cpp
+ }
+}
+
+project(*NPServer) : aceexe {
+ exename = NPServer
+ Source_Files {
+ NPServer.cpp
+ }
+}
+
+project(*producer_msg) : aceexe {
+ exename = producer_msg
+ Source_Files {
+ producer_msg.cpp
+ }
+}
+
+project(*producer_read) : aceexe {
+ exename = producer_read
+ Source_Files {
+ producer_read.cpp
+ }
+}
+
+project(*server) : aceexe {
+ exename = server
+ Source_Files {
+ server.cpp
+ }
+}
diff --git a/ACE/examples/IPC_SAP/SPIPE_SAP/client.cpp b/ACE/examples/IPC_SAP/SPIPE_SAP/client.cpp
new file mode 100644
index 00000000000..ad0ee029dbd
--- /dev/null
+++ b/ACE/examples/IPC_SAP/SPIPE_SAP/client.cpp
@@ -0,0 +1,48 @@
+// $Id$
+
+#include "ace/OS_main.h"
+#include "ace/SPIPE_Addr.h"
+#include "ace/SPIPE_Connector.h"
+#include "ace/Log_Msg.h"
+#include "ace/OS_NS_stdio.h"
+#include "ace/OS_NS_string.h"
+
+ACE_RCSID(SPIPE_SAP, client, "$Id$")
+
+#if defined (ACE_HAS_STREAM_PIPES)
+
+#include "shared.h"
+
+int
+ACE_TMAIN (int argc, ACE_TCHAR *argv[])
+{
+ if (argc < 2)
+ ACE_ERROR_RETURN ((LM_ERROR, "usage: %s string [rendezvous]\n", argv[0]), 1);
+
+ if (argc > 2)
+ rendezvous = argv[2];
+
+ ACE_SPIPE_Stream cli_stream;
+ ACE_SPIPE_Connector con;
+
+ if (con.connect (cli_stream, ACE_SPIPE_Addr (rendezvous)) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, "%p\n", rendezvous), 1);
+
+ ssize_t len = ACE_OS::strlen (argv[1]) + 1;
+
+ if (cli_stream.send (argv[1], len) != len)
+ ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "send"), 1);
+
+ if (cli_stream.close () == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "close"), 1);
+
+ return 0;
+}
+#else
+#include <stdio.h>
+int ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ ACE_OS::fprintf (stderr, "This feature is not supported\n");
+ return 0;
+}
+#endif /* ACE_HAS_STREAM_PIPES */
diff --git a/ACE/examples/IPC_SAP/SPIPE_SAP/consumer_msg.cpp b/ACE/examples/IPC_SAP/SPIPE_SAP/consumer_msg.cpp
new file mode 100644
index 00000000000..daadc20fdf0
--- /dev/null
+++ b/ACE/examples/IPC_SAP/SPIPE_SAP/consumer_msg.cpp
@@ -0,0 +1,59 @@
+// $Id$
+
+#include "ace/OS_main.h"
+#include "ace/SPIPE_Addr.h"
+#include "ace/SPIPE_Acceptor.h"
+#include "ace/Log_Msg.h"
+#include "ace/OS_NS_stdio.h"
+#include "ace/OS_NS_unistd.h"
+#include "ace/Time_Value.h"
+
+ACE_RCSID(SPIPE_SAP, consumer_msg, "$Id$")
+
+#if defined (ACE_HAS_STREAM_PIPES)
+
+#include "shared.h"
+
+int
+ACE_TMAIN (int argc, ACE_TCHAR *argv[])
+{
+ ACE_SPIPE_Acceptor peer_acceptor;
+ ACE_SPIPE_Stream new_stream;
+ char buf[BUFSIZ];
+ ACE_Str_Buf buffer (buf, 0, sizeof buf);
+ int flags = 0;
+
+ if (argc > 1)
+ rendezvous = argv[1];
+
+ ACE_OS::unlink (rendezvous);
+ ACE_OS::fdetach (ACE_TEXT_ALWAYS_CHAR (rendezvous));
+
+ ACE_SPIPE_Addr addr (rendezvous);
+ ACE_Time_Value timeout (ACE_DEFAULT_TIMEOUT);
+
+ if (peer_acceptor.open (addr) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "open"), 1);
+
+ ACE_DEBUG ((LM_DEBUG, "waiting for connection\n"));
+
+ if (peer_acceptor.accept (new_stream, 0, &timeout) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "accept"), 1);
+
+ ACE_DEBUG ((LM_DEBUG, "accepted\n"));
+
+ while (new_stream.recv ((ACE_Str_Buf *) 0, &buffer, &flags) >= 0)
+ if (buffer.len == 0)
+ break;
+ else
+ ACE_OS::write (ACE_STDOUT, buffer.buf, buffer.len);
+ return 0;
+}
+#else
+#include <stdio.h>
+int ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ ACE_OS::fprintf (stderr, "This feature is not supported\n");
+ return 0;
+}
+#endif /* ACE_HAS_STREAM_PIPES */
diff --git a/ACE/examples/IPC_SAP/SPIPE_SAP/consumer_read.cpp b/ACE/examples/IPC_SAP/SPIPE_SAP/consumer_read.cpp
new file mode 100644
index 00000000000..f16c0683680
--- /dev/null
+++ b/ACE/examples/IPC_SAP/SPIPE_SAP/consumer_read.cpp
@@ -0,0 +1,56 @@
+// $Id$
+
+#include "ace/OS_main.h"
+#include "ace/SPIPE_Addr.h"
+#include "ace/SPIPE_Acceptor.h"
+#include "ace/Log_Msg.h"
+#include "ace/OS_NS_stdio.h"
+#include "ace/OS_NS_unistd.h"
+#include "ace/Time_Value.h"
+
+ACE_RCSID(SPIPE_SAP, consumer_read, "$Id$")
+
+#if defined (ACE_HAS_STREAM_PIPES)
+
+#include "shared.h"
+
+int
+ACE_TMAIN (int argc, ACE_TCHAR *argv[])
+{
+ ACE_SPIPE_Acceptor peer_acceptor;
+ ACE_SPIPE_Stream new_stream;
+ char buf[BUFSIZ];
+ int n;
+
+ // Wait up to ACE_DEFAULT_TIMEOUT seconds to accept connection.
+ ACE_Time_Value timeout (ACE_DEFAULT_TIMEOUT);
+
+ if (argc > 1)
+ rendezvous = argv[1];
+
+ ACE_OS::unlink (rendezvous);
+ ACE_OS::fdetach (ACE_TEXT_ALWAYS_CHAR (rendezvous));
+
+ if (peer_acceptor.open (ACE_SPIPE_Addr (rendezvous)) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "open"), 1);
+
+ ACE_DEBUG ((LM_DEBUG, "waiting for connection\n"));
+
+ if (peer_acceptor.accept (new_stream, 0, &timeout) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "accept"), 1);
+
+ ACE_DEBUG ((LM_DEBUG, "accepted\n"));
+
+ while ((n = new_stream.recv (buf, sizeof buf)) > 0)
+ ACE_OS::write (ACE_STDOUT, buf, n);
+
+ return 0;
+}
+#else
+#include <stdio.h>
+int ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ ACE_OS::fprintf (stderr, "This feature is not supported\n");
+ return 0;
+}
+#endif /* ACE_HAS_STREAM_PIPES */
diff --git a/ACE/examples/IPC_SAP/SPIPE_SAP/producer_msg.cpp b/ACE/examples/IPC_SAP/SPIPE_SAP/producer_msg.cpp
new file mode 100644
index 00000000000..619a44f1e71
--- /dev/null
+++ b/ACE/examples/IPC_SAP/SPIPE_SAP/producer_msg.cpp
@@ -0,0 +1,66 @@
+// $Id$
+
+#include "ace/OS_main.h"
+#include "ace/OS_Memory.h"
+#include "ace/SPIPE_Addr.h"
+#include "ace/SPIPE_Connector.h"
+#include "ace/Log_Msg.h"
+#include "ace/OS_NS_stdio.h"
+#include "ace/OS_NS_stdlib.h"
+#include "ace/OS_NS_unistd.h"
+#include "ace/Time_Value.h"
+
+ACE_RCSID(SPIPE_SAP, producer_msg, "$Id$")
+
+#if defined (ACE_HAS_STREAM_PIPES)
+
+#include "shared.h"
+
+const int DEFAULT_SIZE = 4 * 1024;
+const int DEFAULT_COUNT = 100;
+
+int
+ACE_TMAIN (int argc, ACE_TCHAR *argv[])
+{
+ int size = argc > 1 ? ACE_OS::atoi (argv[1]) : DEFAULT_SIZE;
+ int iterations = argc > 2 ? ACE_OS::atoi (argv[2]) : DEFAULT_COUNT;
+ char *buf;
+
+ ACE_NEW_RETURN (buf, char[size], -1);
+
+ if (argc > 3)
+ rendezvous = argv[3];
+
+ ACE_SPIPE_Stream cli_stream;
+ ACE_SPIPE_Connector con;
+ int i;
+
+ if (con.connect (cli_stream, ACE_SPIPE_Addr (rendezvous)) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, "%p\n", rendezvous), 1);
+
+ for (i = 0; i < size; i++)
+ buf[i] = 'a';
+
+ ACE_Str_Buf buffer (buf, size);
+
+ for (i = 0; i < iterations; i++)
+ if (cli_stream.send ((ACE_Str_Buf *) 0,
+ &buffer,
+ 1,
+ MSG_BAND) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "send"), 1);
+
+ if (cli_stream.close () == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "close"), 1);
+
+ delete buf;
+ return 0;
+}
+#else
+#include <stdio.h>
+int ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ ACE_OS::fprintf (stderr, "This feature is not supported\n");
+ return 0;
+}
+#endif /* ACE_HAS_STREAM_PIPES */
diff --git a/ACE/examples/IPC_SAP/SPIPE_SAP/producer_read.cpp b/ACE/examples/IPC_SAP/SPIPE_SAP/producer_read.cpp
new file mode 100644
index 00000000000..f04f7961818
--- /dev/null
+++ b/ACE/examples/IPC_SAP/SPIPE_SAP/producer_read.cpp
@@ -0,0 +1,54 @@
+// $Id$
+
+#include "ace/OS_main.h"
+#include "ace/SPIPE_Addr.h"
+#include "ace/SPIPE_Connector.h"
+#include "ace/Log_Msg.h"
+#include "ace/OS_NS_stdlib.h"
+
+
+ACE_RCSID(SPIPE_SAP, producer_read, "$Id$")
+
+#if defined (ACE_HAS_STREAM_PIPES)
+
+#include "shared.h"
+
+const int DEFAULT_SIZE = 8 * 1024;
+const int DEFAULT_COUNT = 100;
+
+int
+ACE_TMAIN (int argc, ACE_TCHAR *argv[])
+{
+ int size = argc > 1 ? ACE_OS::atoi (argv[1]) : DEFAULT_SIZE;
+ int iterations = argc > 2 ? ACE_OS::atoi (argv[2]) : DEFAULT_COUNT;
+ char *buf = new char[size];
+
+ if (argc > 3)
+ rendezvous = argv[3];
+
+ ACE_SPIPE_Stream cli_stream;
+ ACE_SPIPE_Connector con;
+ int i;
+
+ if (con.connect (cli_stream, ACE_SPIPE_Addr (rendezvous)) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, "%p\n", rendezvous), -1);
+
+ for (i = 0; i < size; i++)
+ buf[i] = 'a';
+
+ for (i = 0; i < iterations; i++)
+ if (cli_stream.send (buf, size) != size)
+ ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "putmsg"), -1);
+
+ if (cli_stream.close () == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "close"), -1);
+
+ return 0;
+}
+#else
+#include <stdio.h>
+int ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ ACE_ERROR_RETURN ((LM_ERROR, "this feature is not supported"), -1);
+}
+#endif /* ACE_HAS_STREAM_PIPES */
diff --git a/ACE/examples/IPC_SAP/SPIPE_SAP/server.cpp b/ACE/examples/IPC_SAP/SPIPE_SAP/server.cpp
new file mode 100644
index 00000000000..bc582f177eb
--- /dev/null
+++ b/ACE/examples/IPC_SAP/SPIPE_SAP/server.cpp
@@ -0,0 +1,124 @@
+// $Id$
+
+#include "ace/OS_main.h"
+#include "ace/SPIPE_Addr.h"
+#include "ace/SPIPE_Acceptor.h"
+#include "ace/Log_Msg.h"
+#include "ace/OS_NS_stdio.h"
+#include "ace/OS_NS_poll.h"
+#include "ace/OS_NS_unistd.h"
+
+ACE_RCSID(SPIPE_SAP, server, "$Id$")
+
+#if defined (ACE_HAS_STREAM_PIPES)
+
+#include "shared.h"
+
+// Maximum per-process open I/O descriptors.
+const int MAX_HANDLES = 200;
+
+int
+ACE_TMAIN (int argc, ACE_TCHAR *argv[])
+{
+ ACE_SPIPE_Acceptor peer_acceptor;
+ ACE_SPIPE_Stream new_stream;
+ struct pollfd poll_array[MAX_HANDLES];
+ ACE_HANDLE handle;
+
+ for (handle = 0; handle < MAX_HANDLES; handle++)
+ {
+ poll_array[handle].fd = -1;
+ poll_array[handle].events = POLLIN;
+ }
+
+ if (argc > 1)
+ rendezvous = argv[1];
+
+ ACE_OS::fdetach (ACE_TEXT_ALWAYS_CHAR (rendezvous));
+ ACE_SPIPE_Addr addr (rendezvous);
+
+ ACE_HANDLE s_handle = peer_acceptor.open (addr);
+
+ if (s_handle == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "peer_acceptor.open"), -1);
+
+ poll_array[0].fd = s_handle;
+
+ for (int width = 1;;)
+ {
+ // Block waiting for client I/O events (handle interrupts).
+ while (ACE_OS::poll (poll_array, width) == -1 && errno == EINTR)
+ continue;
+
+ // Handle pending logging messages first (s_handle + 1 is
+ // guaranteed to be lowest client descriptor).
+
+ for (handle = s_handle + 1; handle < width; handle++)
+ if (ACE_BIT_ENABLED (poll_array[handle].revents, POLLIN)
+ || ACE_BIT_ENABLED (poll_array[handle].revents, POLLHUP))
+ {
+ char buf[BUFSIZ];
+ ssize_t n = ACE_OS::read (handle, buf, sizeof buf);
+
+ // recv will not block in this case!
+ if (n == -1)
+ ACE_DEBUG ((LM_DEBUG, "%p\n", "read failed"));
+ else if (n == 0)
+ {
+ // Handle client connection shutdown.
+ if (ACE_OS::close (poll_array[handle].fd) == -1)
+ ACE_DEBUG ((LM_DEBUG, "%p\n", "close"));
+ poll_array[handle].fd = -1;
+
+ if (handle + 1 == width)
+ {
+ while (poll_array[handle].fd == -1)
+ handle--;
+ width = handle + 1;
+ }
+ }
+ else
+ ACE_DEBUG ((LM_DEBUG, "%*s\n", n, buf));
+ }
+
+ if (ACE_BIT_ENABLED (poll_array[0].revents, POLLIN))
+ {
+ if (peer_acceptor.accept (new_stream) == -1)
+ ACE_DEBUG ((LM_DEBUG, "%p\n", "accept failed"));
+
+ ACE_SPIPE_Addr client;
+ ACE_HANDLE n_handle = new_stream.get_handle ();
+
+ if (new_stream.get_remote_addr (client) == -1)
+ ACE_DEBUG ((LM_DEBUG, "%p\n",
+ "get_remote_addr failed"));
+
+ ACE_DEBUG ((LM_DEBUG,
+ "n_handle = %d, uid = %d, gid = %d\n",
+ n_handle,
+ client.user_id (),
+ client.group_id ()));
+
+ int arg = RMSGN | RPROTDAT;
+
+ if (ACE_OS::ioctl (n_handle,
+ I_SRDOPT, (void *) arg) == -1)
+ ACE_DEBUG ((LM_DEBUG, "%p\n", "ioctl failed"));
+
+ poll_array[n_handle].fd = n_handle;
+
+ if (n_handle >= width)
+ width = n_handle + 1;
+ }
+ }
+
+ ACE_NOTREACHED (return 0;)
+}
+#else
+#include <stdio.h>
+int ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ ACE_OS::fprintf (stderr, "This feature is not supported\n");
+ return 0;
+}
+#endif /* ACE_HAS_STREAM_PIPES */
diff --git a/ACE/examples/IPC_SAP/SPIPE_SAP/shared.h b/ACE/examples/IPC_SAP/SPIPE_SAP/shared.h
new file mode 100644
index 00000000000..47f2e8db6bc
--- /dev/null
+++ b/ACE/examples/IPC_SAP/SPIPE_SAP/shared.h
@@ -0,0 +1,10 @@
+/* -*- C++ -*- */
+// $Id$
+
+#include "ace/config-all.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+static const ACE_TCHAR *rendezvous = ACE_DEFAULT_RENDEZVOUS;
diff --git a/ACE/examples/IPC_SAP/SSL_SAP/Makefile.am b/ACE/examples/IPC_SAP/SSL_SAP/Makefile.am
new file mode 100644
index 00000000000..3df4d11db5b
--- /dev/null
+++ b/ACE/examples/IPC_SAP/SSL_SAP/Makefile.am
@@ -0,0 +1,196 @@
+## Process this file with automake to create Makefile.in
+##
+## $Id$
+##
+## This file was generated by MPC. Any changes made directly to
+## this file will be lost the next time it is generated.
+##
+## MPC Command:
+## /acebuilds/ACE_wrappers-repository/bin/mwc.pl -include /acebuilds/MPC/config -include /acebuilds/MPC/templates -feature_file /acebuilds/ACE_wrappers-repository/local.features -noreldefs -type automake -exclude build,Kokyu
+
+ACE_BUILDDIR = $(top_builddir)
+ACE_ROOT = $(top_srcdir)
+
+noinst_PROGRAMS =
+
+## Makefile.SSL_SAP_Client.am
+
+if BUILD_SSL
+if !BUILD_ACE_FOR_TAO
+
+noinst_PROGRAMS += client
+
+client_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR) \
+ -DACE_HAS_SSL=1 \
+ @ACE_TLS_CPPFLAGS@
+
+client_SOURCES = \
+ SSL-client.cpp \
+ SSL-client.h
+
+client_LDFLAGS = \
+ @ACE_TLS_LDFLAGS@
+
+client_LDADD = \
+ $(ACE_BUILDDIR)/ace/SSL/libACE_SSL.la \
+ $(ACE_BUILDDIR)/ace/libACE.la \
+ @ACE_TLS_LIBS@
+
+endif !BUILD_ACE_FOR_TAO
+endif BUILD_SSL
+
+## Makefile.SSL_SAP_Client_Simple.am
+
+if BUILD_SSL
+if !BUILD_ACE_FOR_TAO
+
+noinst_PROGRAMS += client-simple
+
+client_simple_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR) \
+ -DACE_HAS_SSL=1 \
+ @ACE_TLS_CPPFLAGS@
+
+client_simple_SOURCES = \
+ SSL-client-simple.cpp \
+ SSL-client-simple.h
+
+client_simple_LDFLAGS = \
+ @ACE_TLS_LDFLAGS@
+
+client_simple_LDADD = \
+ $(ACE_BUILDDIR)/ace/SSL/libACE_SSL.la \
+ $(ACE_BUILDDIR)/ace/libACE.la \
+ @ACE_TLS_LIBS@
+
+endif !BUILD_ACE_FOR_TAO
+endif BUILD_SSL
+
+## Makefile.SSL_SAP_Server.am
+
+if BUILD_SSL
+if !BUILD_ACE_FOR_TAO
+
+noinst_PROGRAMS += server
+
+server_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR) \
+ -DACE_HAS_SSL=1 \
+ @ACE_TLS_CPPFLAGS@
+
+server_SOURCES = \
+ SSL-server.cpp \
+ SSL-client-simple.h \
+ SSL-client.h \
+ SSL-server-fancy.h
+
+server_LDFLAGS = \
+ @ACE_TLS_LDFLAGS@
+
+server_LDADD = \
+ $(ACE_BUILDDIR)/ace/SSL/libACE_SSL.la \
+ $(ACE_BUILDDIR)/ace/libACE.la \
+ @ACE_TLS_LIBS@
+
+endif !BUILD_ACE_FOR_TAO
+endif BUILD_SSL
+
+## Makefile.SSL_SAP_Server_Fancy.am
+
+if BUILD_SSL
+if !BUILD_ACE_FOR_TAO
+
+noinst_PROGRAMS += server-fancy
+
+server_fancy_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR) \
+ -DACE_HAS_SSL=1 \
+ @ACE_TLS_CPPFLAGS@
+
+server_fancy_SOURCES = \
+ SSL-server-fancy.cpp \
+ SSL-server-fancy.h
+
+server_fancy_LDFLAGS = \
+ @ACE_TLS_LDFLAGS@
+
+server_fancy_LDADD = \
+ $(ACE_BUILDDIR)/ace/SSL/libACE_SSL.la \
+ $(ACE_BUILDDIR)/ace/libACE.la \
+ @ACE_TLS_LIBS@
+
+endif !BUILD_ACE_FOR_TAO
+endif BUILD_SSL
+
+## Makefile.SSL_SAP_Server_Poll.am
+
+if BUILD_SSL
+if !BUILD_ACE_FOR_TAO
+
+noinst_PROGRAMS += server-poll
+
+server_poll_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR) \
+ -DACE_HAS_SSL=1 \
+ @ACE_TLS_CPPFLAGS@
+
+server_poll_SOURCES = \
+ SSL-server-poll.cpp \
+ SSL-client-simple.h \
+ SSL-client.h \
+ SSL-server-fancy.h
+
+server_poll_LDFLAGS = \
+ @ACE_TLS_LDFLAGS@
+
+server_poll_LDADD = \
+ $(ACE_BUILDDIR)/ace/SSL/libACE_SSL.la \
+ $(ACE_BUILDDIR)/ace/libACE.la \
+ @ACE_TLS_LIBS@
+
+endif !BUILD_ACE_FOR_TAO
+endif BUILD_SSL
+
+## Makefile.SSL_SAP_Server_Simple.am
+
+if BUILD_SSL
+if !BUILD_ACE_FOR_TAO
+
+noinst_PROGRAMS += server-simple
+
+server_simple_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR) \
+ -DACE_HAS_SSL=1 \
+ @ACE_TLS_CPPFLAGS@
+
+server_simple_SOURCES = \
+ SSL-server-simple.cpp \
+ SSL-client-simple.h \
+ SSL-client.h \
+ SSL-server-fancy.h
+
+server_simple_LDFLAGS = \
+ @ACE_TLS_LDFLAGS@
+
+server_simple_LDADD = \
+ $(ACE_BUILDDIR)/ace/SSL/libACE_SSL.la \
+ $(ACE_BUILDDIR)/ace/libACE.la \
+ @ACE_TLS_LIBS@
+
+endif !BUILD_ACE_FOR_TAO
+endif BUILD_SSL
+
+## Clean up template repositories, etc.
+clean-local:
+ -rm -f *~ *.bak *.rpo *.sym lib*.*_pure_* core core.*
+ -rm -f gcctemp.c gcctemp so_locations *.ics
+ -rm -rf cxx_repository ptrepository ti_files
+ -rm -rf templateregistry ir.out
+ -rm -rf ptrepository SunWS_cache Templates.DB
diff --git a/ACE/examples/IPC_SAP/SSL_SAP/README b/ACE/examples/IPC_SAP/SSL_SAP/README
new file mode 100644
index 00000000000..43f4640e75a
--- /dev/null
+++ b/ACE/examples/IPC_SAP/SSL_SAP/README
@@ -0,0 +1,17 @@
+# $Id$
+
+This directory contains groups of client and server test programs that
+exercise the various C++ wrappers for SSL sockets. In general, the
+test programs do more or less the same thing -- the client establishes
+a connection with the server and then transfers data to the server,
+which keeps printing the data until EOF is reached (e.g., user types
+^D).
+
+Unless noted differently, the server is implemented as an "iterative
+server," i.e., it only deals with one client at a time. The following
+describes each set of tests in more detail:
+
+ . SSL-{client,server}.cpp -- This test allows you to test
+ oneway and twoway socket communication latency and
+ throughput over SSL between two processes on the same
+ machine or on different machines.
diff --git a/ACE/examples/IPC_SAP/SSL_SAP/SSL-client-simple.cpp b/ACE/examples/IPC_SAP/SSL_SAP/SSL-client-simple.cpp
new file mode 100644
index 00000000000..31f76d4826a
--- /dev/null
+++ b/ACE/examples/IPC_SAP/SSL_SAP/SSL-client-simple.cpp
@@ -0,0 +1,377 @@
+// $Id$
+
+// This tests the features of the <ACE_SSL_SOCK_Connector> and
+// <ACE_SSL_SOCK_Stream> classes. In addition, it can be used to test the
+// oneway and twoway latency and throughput at the socket-level. This
+// is useful as a baseline to compare against ORB-level performance
+// for the same types of data.
+
+#include "ace/OS_NS_string.h"
+#include "ace/OS_NS_unistd.h"
+#include "ace/INET_Addr.h"
+#include "ace/Log_Msg.h"
+#include "ace/Singleton.h"
+#include "ace/Get_Opt.h"
+#include "ace/High_Res_Timer.h"
+#include "ace/Null_Mutex.h"
+
+#include "ace/SSL/SSL_SOCK_Connector.h"
+
+#include "SSL-client-simple.h"
+
+ACE_RCSID (SSL_SAP,
+ SSL_client_simple,
+ "$Id$")
+
+
+Options::Options (void)
+ : host_ (ACE_DEFAULT_SERVER_HOST),
+ port_ (ACE_DEFAULT_SERVER_PORT),
+ sleep_time_ (0, 0), // By default, don't sleep between calls.
+ message_len_ (0),
+ message_buf_ (0),
+ io_source_ (ACE_INVALID_HANDLE), // Defaults to using the generator.
+ iterations_ (10000),
+ oneway_ (1) // Make oneway calls the default.
+{
+ ACE_OS::strcpy (quit_string_, "q");
+}
+
+Options::~Options (void)
+{
+ delete [] this->message_buf_;
+}
+
+// Options Singleton.
+typedef ACE_Singleton<Options, ACE_Null_Mutex> OPTIONS;
+
+int
+Options::init (void)
+{
+ // Check for default case.
+ if (this->message_len_ == 0)
+ this->message_len_ = ACE_OS::strlen ("TAO");
+
+ this->message_len_ += sizeof (ACE_UINT32);
+
+ ACE_NEW_RETURN (this->message_buf_,
+ char[this->message_len_],
+ -1);
+
+ // Copy the length into the beginning of the message.
+ ACE_UINT32 length = ntohl (this->message_len_);
+ ACE_OS::memcpy ((void *) this->message_buf_,
+ (void *) &length,
+ sizeof length);
+
+ ACE_OS::memset ((void *) (this->message_buf_ + sizeof (ACE_UINT32)),
+ 'a',
+ this->message_len_ - sizeof (ACE_UINT32));
+
+ return 0;
+}
+
+size_t
+Options::message_len (void) const
+{
+ return this->message_len_;
+}
+
+const void *
+Options::message_buf (void) const
+{
+ return this->message_buf_;
+}
+
+ssize_t
+Options::read (void *buf, size_t len, size_t &iteration)
+{
+ ACE_UNUSED_ARG (len);
+
+ if (this->io_source_ == ACE_STDIN)
+ return ACE_OS::read (ACE_STDIN, buf, len);
+ else if (iteration >= this->iterations_)
+ return 0;
+ else
+ {
+ ACE_OS::memcpy (buf,
+ this->message_buf (),
+ len);
+ iteration++;
+ return len;
+ }
+}
+
+int
+Options::parse_args (int argc, ACE_TCHAR *argv[])
+{
+ ACE_Get_Opt getopt (argc, argv, ACE_TEXT ("2h:i:m:p:q:sT:"), 1);
+
+ for (int c; (c = getopt ()) != -1; )
+ switch (c)
+ {
+ case '2': // Disable the oneway client.
+ this->oneway_ = 0;
+ break;
+ case 'h':
+ this->host_ = getopt.opt_arg ();
+ break;
+ case 'i':
+ this->iterations_ = ACE_OS::atoi (getopt.opt_arg ());
+ break;
+ case 'm':
+ this->message_len_ = ACE_OS::atoi (getopt.opt_arg ());
+ break;
+ case 'p':
+ this->port_ = ACE_OS::atoi (getopt.opt_arg ());
+ break;
+ case 'q':
+ ACE_OS::strncpy (this->quit_string_,
+ ACE_TEXT_ALWAYS_CHAR (getopt.opt_arg ()),
+ QUIT_STRING_SIZE);
+ break;
+ case 's':
+ this->io_source_ = ACE_STDIN;
+ break;
+ case 'T':
+ this->sleep_time_.set (0, ACE_OS::atoi (getopt.opt_arg ()));
+ break;
+ default:
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("(%P|%t) usage: %n [-2] [-h <host>] ")
+ ACE_TEXT ("[-i iterations] [-m message-size] ")
+ ACE_TEXT ("[-p <port>] [-q <quit string>] ")
+ ACE_TEXT ("[-s] [-T <sleep_time>]\n")),
+ -1);
+ }
+
+ return this->init ();
+}
+
+u_short
+Options::port (void) const
+{
+ return this->port_;
+}
+
+const ACE_TCHAR *
+Options::host (void) const
+{
+ return this->host_;
+}
+
+const char *
+Options::quit_string (void) const
+{
+ return this->quit_string_;
+}
+
+const ACE_Time_Value &
+Options::sleep_time (void) const
+{
+ return this->sleep_time_;
+}
+
+char *
+Options::shared_client_test (u_short port,
+ ACE_SSL_SOCK_Stream &cli_stream)
+{
+ ACE_INET_Addr remote_addr (port, this->host_);
+
+ ACE_SSL_SOCK_Connector con;
+
+ if (con.connect (cli_stream,
+ remote_addr) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("(%P|%t) %p\n"),
+ ACE_TEXT ("connection failed")),
+ 0);
+ else
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("(%P|%t) connected to %C at port %d\n"),
+ remote_addr.get_host_name (),
+ remote_addr.get_port_number ()));
+
+ char *buf;
+ ACE_NEW_RETURN (buf,
+ char[this->message_len ()],
+ 0);
+
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("(%P|%t) waiting...\n")));
+
+ return buf;
+}
+// Static function entry point to the oneway client service.
+
+void
+Options::oneway_client_test (void)
+{
+ ACE_SSL_SOCK_Stream cli_stream;
+
+ // Add 1 to the port to trigger the oneway test!
+ char *request = this->shared_client_test (this->port () + 1,
+ cli_stream);
+ if (request == 0)
+ return;
+
+ // This variable is allocated off the stack to obviate the need for
+ // locking.
+ size_t iteration = 0;
+
+ // Keep track of return value.
+ int result = 0;
+ ACE_INT32 len = this->message_len ();
+
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("(%P|%t) starting oneway transmission\n")));
+
+ // Perform oneway transmission of data to server (correctly handles
+ // "incomplete writes").
+
+ for (ssize_t r_bytes;
+ (r_bytes = this->read (request, len, iteration)) > 0;
+ // Transmit at the proper rate.
+ ACE_OS::sleep (this->sleep_time ()))
+ if (ACE_OS::memcmp (request,
+ this->quit_string (),
+ ACE_OS::strlen (this->quit_string ())) == 0)
+ break;
+ else if (cli_stream.send_n (request, r_bytes) == -1)
+ {
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("(%P|%t) %p\n"),
+ ACE_TEXT ("send_n")));
+ result = -1;
+ break;
+ }
+
+ // Close the connection.
+ cli_stream.close ();
+
+ delete [] request;
+}
+
+// Static function entry point to the twoway client service.
+
+void
+Options::twoway_client_test (void)
+{
+ ACE_SSL_SOCK_Stream cli_stream;
+
+ char *request = this->shared_client_test (this->port (),
+ cli_stream);
+ if (request == 0)
+ return;
+
+ // This variable is allocated off the stack to obviate the need for
+ // locking.
+ size_t iteration = 0;
+
+ // Keep track of return value.
+ int result = 0;
+
+ // Timer business.
+ ACE_High_Res_Timer timer;
+
+ ACE_INT32 len = this->message_len ();
+
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("(%P|%t) starting twoway transmission\n")));
+
+ // Perform twoway transmission of data to server (correctly handles
+ // "incomplete writes").
+
+ for (ssize_t r_bytes;
+ (r_bytes = this->read (request, len, iteration)) > 0;
+ // Transmit at the proper rate.
+ ACE_OS::sleep (this->sleep_time ()))
+ if (ACE_OS::memcmp (request,
+ this->quit_string (),
+ ACE_OS::strlen (this->quit_string ())) == 0)
+ break;
+
+ // Transmit <request> to the server.
+ else
+ {
+ // Note that we use the incremental feature of the
+ // <ACE_High_Res_Timer> so that we don't get "charged" for the
+ // <ACE_OS::sleep> used to control the rate at which requests
+ // are sent.
+ timer.start_incr ();
+
+ if (cli_stream.send_n (request, r_bytes) == -1)
+ {
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("(%P|%t) %p\n"),
+ ACE_TEXT ("send_n")));
+ result = -1;
+ break;
+ }
+ // Receive the reply from the server. Normally, it just sends
+ // back 24 bytes, which is typical for an IIOP reply.
+ else if (cli_stream.recv (request, r_bytes) <= 0)
+ {
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("(%P|%t) %p\n"),
+ ACE_TEXT ("recv")));
+ result = -1;
+ break;
+ }
+
+ timer.stop_incr ();
+ }
+
+ ACE_Time_Value tv;
+
+ timer.elapsed_time_incr (tv);
+ double real_time = tv.sec () * ACE_ONE_SECOND_IN_USECS + tv.usec ();
+ double messages_per_sec = iteration * double (ACE_ONE_SECOND_IN_USECS) / real_time;
+
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("(%t) messages = %d\n(%t) usec-per-message = %f\n(%t) messages-per-second = %0.00f\n"),
+ iteration,
+ real_time / double (iteration),
+ messages_per_sec < 0 ? 0 : messages_per_sec));
+
+ // Close the connection.
+ cli_stream.close ();
+
+ delete [] request;
+}
+
+void
+Options::run (void)
+{
+ if (this->oneway_ == 0)
+ this->twoway_client_test ();
+ else
+ this->oneway_client_test ();
+}
+
+static int
+run_client (void)
+{
+ // Raise the socket handle limit to the maximum.
+ ACE::set_handle_limit ();
+
+ OPTIONS::instance ()->run ();
+
+ return 0;
+}
+
+int
+ACE_TMAIN (int argc, ACE_TCHAR *argv[])
+{
+ // Initialize the logger.
+ ACE_LOG_MSG->open (argv[0]);
+
+ if (OPTIONS::instance ()->parse_args (argc, argv) == -1)
+ return -1;
+
+ // Run the client
+ run_client ();
+
+ return 0;
+}
+
diff --git a/ACE/examples/IPC_SAP/SSL_SAP/SSL-client-simple.h b/ACE/examples/IPC_SAP/SSL_SAP/SSL-client-simple.h
new file mode 100644
index 00000000000..4ec6b815a4c
--- /dev/null
+++ b/ACE/examples/IPC_SAP/SSL_SAP/SSL-client-simple.h
@@ -0,0 +1,98 @@
+// -*- C++ -*-
+// $Id$
+
+// This file defines the Options class for SSL-client-simple. IBM C++
+// compiler's template auto-instantiator needs this in a separate file.
+
+#ifndef ACE_SSL_CLIENT_SIMPLE_H
+#define ACE_SSL_CLIENT_SIMPLE_H
+
+#include "ace/SSL/SSL_SOCK_Stream.h"
+#include "ace/Time_Value.h"
+
+class Options
+ // = TITLE
+ // Define the options for this test.
+{
+public:
+ Options (void);
+ // Constructor.
+
+ ~Options (void);
+ // Destructor.
+
+ int parse_args (int argc, ACE_TCHAR *argv[]);
+ // Parse the command-line arguments.
+
+ const ACE_Time_Value &sleep_time (void) const;
+ // Return the amount of time to sleep in order to implement the
+ // proper transmission rates.
+
+ u_short port (void) const;
+ // Port of the server.
+
+ const ACE_TCHAR *host (void) const;
+ // Host of the server.
+
+ const char *quit_string (void) const;
+ // String that shuts down the client/server.
+
+ ssize_t read (void *buf, size_t len, size_t &iterations);
+ // Read from the appropriate location.
+
+ size_t message_len (void) const;
+ // Returns the length of the message to send.
+
+ const void *message_buf (void) const;
+ // Returns a pointer to the message.
+
+ void run (void);
+ // Run the test
+
+private:
+ int init (void);
+ // Initialize the message we're sending to the user and set up the
+ // barrier.
+
+ char *shared_client_test (u_short port,
+ ACE_SSL_SOCK_Stream &cli_stream);
+ // Performs the shared behavior of the oneway and twoway client
+ // tests.
+
+ void twoway_client_test (void);
+ // Performs the twoway test.
+
+ void oneway_client_test (void);
+ // Performs the oneway test.
+
+ const ACE_TCHAR *host_;
+ // Host of the server.
+
+ u_short port_;
+ // Port of the server.
+
+ ACE_Time_Value sleep_time_;
+ // Sleep_Time value.
+
+ enum {QUIT_STRING_SIZE = 128};
+ char quit_string_[QUIT_STRING_SIZE];
+ // String that shuts down the client/server.
+
+ size_t message_len_;
+ // Size of the message we send to the server.
+
+ char *message_buf_;
+ // Pointer to the message we send to the server.
+
+ ACE_HANDLE io_source_;
+ // Are we reading I/O from ACE_STDIN or from our generator?
+
+ size_t iterations_;
+ // Number of iterations.
+
+ char oneway_;
+ // Are we running oneway or twoway?
+
+};
+
+#endif /* ACE_SSL_CLIENT_SIMPLE_H */
diff --git a/ACE/examples/IPC_SAP/SSL_SAP/SSL-client.cpp b/ACE/examples/IPC_SAP/SSL_SAP/SSL-client.cpp
new file mode 100644
index 00000000000..539b97c931c
--- /dev/null
+++ b/ACE/examples/IPC_SAP/SSL_SAP/SSL-client.cpp
@@ -0,0 +1,418 @@
+// $Id$
+
+// This tests the features of the <ACE_SSL_SOCK_Connector> and
+// <ACE_SSL_SOCK_Stream> classes. In addition, it can be used to test the
+// oneway and twoway latency and throughput at the socket-level. This
+// is useful as a baseline to compare against ORB-level performance
+// for the same types of data.
+
+#include "ace/OS_NS_string.h"
+#include "ace/OS_NS_unistd.h"
+#include "ace/INET_Addr.h"
+#include "ace/Thread_Manager.h"
+#include "ace/Singleton.h"
+#include "ace/Get_Opt.h"
+#include "ace/High_Res_Timer.h"
+
+#include "ace/SSL/SSL_SOCK_Connector.h"
+
+#include "SSL-client.h"
+
+ACE_RCSID(SSL_SAP, SSL_client, "$Id$")
+
+Options::Options (void)
+ : host_ (ACE_DEFAULT_SERVER_HOST),
+ port_ (ACE_DEFAULT_SERVER_PORT),
+ sleep_time_ (0, 0), // By default, don't sleep between calls.
+ threads_ (10),
+ message_len_ (0),
+ message_buf_ (0),
+ io_source_ (ACE_INVALID_HANDLE), // Defaults to using the generator.
+ iterations_ (10000),
+ oneway_ (1) // Make oneway calls the default.
+#if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0)
+ , barrier_ (0)
+#endif /* ACE_MT_SAFE */
+{
+ ACE_OS::strcpy (quit_string_, "q");
+}
+
+Options::~Options (void)
+{
+ ACE_MT (delete this->barrier_);
+ delete [] this->message_buf_;
+}
+
+// Options Singleton.
+typedef ACE_Singleton<Options, ACE_SYNCH_RECURSIVE_MUTEX> OPTIONS;
+
+int
+Options::init (void)
+{
+ // Check for default case.
+ if (this->message_len_ == 0)
+ this->message_len_ = ACE_OS::strlen ("TAO");
+
+ this->message_len_ += sizeof (ACE_UINT32);
+
+ ACE_NEW_RETURN (this->message_buf_,
+ char[this->message_len_],
+ -1);
+
+ // Copy the length into the beginning of the message.
+ ACE_UINT32 length = ntohl (this->message_len_);
+ ACE_OS::memcpy ((void *) this->message_buf_,
+ (void *) &length,
+ sizeof length);
+
+ ACE_OS::memset ((void *) (this->message_buf_ + sizeof (ACE_UINT32)),
+ 'a',
+ this->message_len_ - sizeof (ACE_UINT32));
+
+ // Allocate the barrier with the correct count.
+ ACE_MT (ACE_NEW_RETURN (this->barrier_,
+ ACE_Barrier (this->threads_),
+ -1));
+ return 0;
+}
+
+size_t
+Options::message_len (void) const
+{
+ return this->message_len_;
+}
+
+const void *
+Options::message_buf (void) const
+{
+ return this->message_buf_;
+}
+
+ssize_t
+Options::read (void *buf, size_t len, size_t &iteration)
+{
+ ACE_UNUSED_ARG (len);
+
+ if (this->io_source_ == ACE_STDIN)
+ return ACE_OS::read (ACE_STDIN, buf, len);
+ else if (iteration >= this->iterations_)
+ return 0;
+ else
+ {
+ ACE_OS::memcpy (buf,
+ this->message_buf (),
+ len);
+ iteration++;
+ return len;
+ }
+}
+
+int
+Options::parse_args (int argc, ACE_TCHAR *argv[])
+{
+ ACE_Get_Opt getopt (argc, argv, ACE_TEXT ("2h:i:m:p:q:st:T:"), 1);
+
+ for (int c; (c = getopt ()) != -1; )
+ switch (c)
+ {
+ case '2': // Disable the oneway client.
+ this->oneway_ = 0;
+ break;
+ case 'h':
+ this->host_ = getopt.opt_arg ();
+ break;
+ case 'i':
+ this->iterations_ = ACE_OS::atoi (getopt.opt_arg ());
+ break;
+ case 'm':
+ this->message_len_ = ACE_OS::atoi (getopt.opt_arg ());
+ break;
+ case 'p':
+ this->port_ = ACE_OS::atoi (getopt.opt_arg ());
+ break;
+ case 'q':
+ ACE_OS::strncpy (this->quit_string_,
+ ACE_TEXT_ALWAYS_CHAR (getopt.opt_arg ()),
+ QUIT_STRING_SIZE);
+ break;
+ case 's':
+ this->io_source_ = ACE_STDIN;
+ break;
+ case 't':
+ this->threads_ = (size_t) ACE_OS::atoi (getopt.opt_arg ());
+ break;
+ case 'T':
+ this->sleep_time_.set (0, ACE_OS::atoi (getopt.opt_arg ()));
+ break;
+ default:
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("(%P|%t) usage: %n [-2] [-h <host>] ")
+ ACE_TEXT ("[-i iterations] [-m message-size] ")
+ ACE_TEXT ("[-p <port>] [-q <quit string>] ")
+ ACE_TEXT ("[-s] [-t <threads>] [-T <sleep_time>]\n")),
+ -1);
+ }
+
+ return this->init ();
+}
+
+u_short
+Options::port (void) const
+{
+ return this->port_;
+}
+
+const ACE_TCHAR *
+Options::host (void) const
+{
+ return this->host_;
+}
+
+const char *
+Options::quit_string (void) const
+{
+ return this->quit_string_;
+}
+
+size_t
+Options::threads (void) const
+{
+ return this->threads_;
+}
+
+const ACE_Time_Value &
+Options::sleep_time (void) const
+{
+ return this->sleep_time_;
+}
+
+char *
+Options::shared_client_test (u_short port,
+ ACE_SSL_SOCK_Stream &cli_stream)
+{
+ ACE_INET_Addr remote_addr (port, this->host_);
+
+ ACE_SSL_SOCK_Connector con;
+
+ if (con.connect (cli_stream,
+ remote_addr) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("(%P|%t) %p\n"),
+ ACE_TEXT ("connection failed")),
+ 0);
+ else
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("(%P|%t) connected to %C at port %d\n"),
+ remote_addr.get_host_name (),
+ remote_addr.get_port_number ()));
+
+ // Allocate the transmit buffer.
+ char *buf;
+ ACE_NEW_RETURN (buf,
+ char[this->message_len ()],
+ 0);
+
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("(%P|%t) waiting...\n")));
+
+ // Wait for all other threads to finish initialization.
+ ACE_MT (this->barrier_->wait ());
+ return buf;
+}
+// Static function entry point to the oneway client service.
+
+void *
+Options::oneway_client_test (void *)
+{
+ Options *options = OPTIONS::instance ();
+ ACE_SSL_SOCK_Stream cli_stream;
+
+ // Add 1 to the port to trigger the oneway test!
+ char *request = options->shared_client_test (options->port () + 1,
+ cli_stream);
+ if (request == 0)
+ return 0;
+
+ // This variable is allocated off the stack to obviate the need for
+ // locking.
+ size_t iteration = 0;
+
+ // Keep track of return value.
+ size_t result = 0;
+ ACE_INT32 len = options->message_len ();
+
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("(%P|%t) starting oneway transmission\n")));
+
+ // Perform oneway transmission of data to server (correctly handles
+ // "incomplete writes").
+
+ for (ssize_t r_bytes;
+ (r_bytes = options->read (request, len, iteration)) > 0;
+ // Transmit at the proper rate.
+ ACE_OS::sleep (options->sleep_time ()))
+ if (ACE_OS::memcmp (request,
+ options->quit_string (),
+ ACE_OS::strlen (options->quit_string ())) == 0)
+ break;
+ else if (cli_stream.send_n (request, r_bytes) == -1)
+ {
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("(%P|%t) %p\n"),
+ ACE_TEXT ("send_n")));
+ result = size_t (-1);
+ break;
+ }
+
+ // Close the connection.
+ cli_stream.close ();
+
+ delete [] request;
+ return (void *) result;
+}
+
+// Static function entry point to the twoway client service.
+
+void *
+Options::twoway_client_test (void *)
+{
+ Options *options = OPTIONS::instance ();
+
+ ACE_SSL_SOCK_Stream cli_stream;
+
+ char *request = options->shared_client_test (options->port (),
+ cli_stream);
+ if (request == 0)
+ return 0;
+
+ // This variable is allocated off the stack to obviate the need for
+ // locking.
+ size_t iteration = 0;
+
+ // Keep track of return value.
+ size_t result = 0;
+
+ // Timer business.
+ ACE_High_Res_Timer timer;
+
+ ACE_INT32 len = options->message_len ();
+
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("(%P|%t) starting twoway transmission\n")));
+
+ // Perform twoway transmission of data to server (correctly handles
+ // "incomplete writes").
+
+ for (ssize_t r_bytes;
+ (r_bytes = options->read (request, len, iteration)) > 0;
+ // Transmit at the proper rate.
+ ACE_OS::sleep (options->sleep_time ()))
+ if (ACE_OS::memcmp (request,
+ options->quit_string (),
+ ACE_OS::strlen (options->quit_string ())) == 0)
+ break;
+
+ // Transmit <request> to the server.
+ else
+ {
+ // Note that we use the incremental feature of the
+ // <ACE_High_Res_Timer> so that we don't get "charged" for the
+ // <ACE_OS::sleep> used to control the rate at which requests
+ // are sent.
+ timer.start_incr ();
+
+ if (cli_stream.send_n (request, r_bytes) == -1)
+ {
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("(%P|%t) %p\n"),
+ ACE_TEXT ("send_n")));
+ result = size_t (-1);
+ break;
+ }
+ // Receive the reply from the server. Normally, it just sends
+ // back 24 bytes, which is typical for an IIOP reply.
+ else if (cli_stream.recv (request, r_bytes) <= 0)
+ {
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("(%P|%t) %p\n"),
+ ACE_TEXT ("recv")));
+ result = size_t (-1);
+ break;
+ }
+
+ timer.stop_incr ();
+ }
+
+ ACE_Time_Value tv;
+
+ timer.elapsed_time_incr (tv);
+ double real_time = tv.sec () * ACE_ONE_SECOND_IN_USECS + tv.usec ();
+ double messages_per_sec =
+ iteration * double (ACE_ONE_SECOND_IN_USECS) / real_time;
+
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("(%t) messages = %d\n")
+ ACE_TEXT ("(%t) usec-per-message = %f\n")
+ ACE_TEXT ("(%t) messages-per-second = %0.00f\n"),
+ iteration,
+ real_time / double (iteration),
+ messages_per_sec < 0 ? 0 : messages_per_sec));
+
+ // Close the connection.
+ cli_stream.close ();
+
+ delete [] request;
+ return (void *) result;
+}
+
+ACE_THR_FUNC
+Options::thr_func (void)
+{
+ if (this->oneway_ == 0)
+ return ACE_THR_FUNC (&Options::twoway_client_test);
+ else
+ return ACE_THR_FUNC (&Options::oneway_client_test);
+}
+
+static int
+run_client (void)
+{
+ // Raise the socket handle limit to the maximum.
+ ACE::set_handle_limit ();
+
+#if defined (ACE_HAS_THREADS)
+ if (ACE_Thread_Manager::instance ()->spawn_n (
+ OPTIONS::instance ()->threads (),
+ OPTIONS::instance ()->thr_func ()) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("(%P|%t) %p\n"),
+ ACE_TEXT ("spawn_n")),
+ 1);
+ else
+ ACE_Thread_Manager::instance ()->wait ();
+#else
+ *(OPTIONS::instance ()->thr_func) ();
+#endif /* ACE_HAS_THREADS */
+ return 0;
+}
+
+int
+ACE_TMAIN (int argc, ACE_TCHAR *argv[])
+{
+ ACE_SSL_Context *context = ACE_SSL_Context::instance ();
+
+ context->certificate ("./dummy.pem", SSL_FILETYPE_PEM);
+ context->private_key ("./key.pem", SSL_FILETYPE_PEM);
+
+ // Initialize the logger.
+ ACE_LOG_MSG->open (argv[0]);
+
+ if (OPTIONS::instance ()->parse_args (argc, argv) == -1)
+ return -1;
+
+ // Run the client
+ run_client ();
+
+ return 0;
+}
+
diff --git a/ACE/examples/IPC_SAP/SSL_SAP/SSL-client.h b/ACE/examples/IPC_SAP/SSL_SAP/SSL-client.h
new file mode 100644
index 00000000000..af081004368
--- /dev/null
+++ b/ACE/examples/IPC_SAP/SSL_SAP/SSL-client.h
@@ -0,0 +1,111 @@
+// -*- C++ -*-
+// $Id$
+
+// This file defines the Options class for SSL-client. IBM C++ compiler'd
+// template auto-instantiator needs this in a separate file.
+
+#ifndef __ACE_SSL_CLIENT_H
+#define __ACE_SSL_CLIENT_H
+
+#include "ace/Barrier.h"
+#include "ace/Time_Value.h"
+
+#include "ace/SSL/SSL_SOCK_Stream.h"
+
+class Options
+ // = TITLE
+ // Define the options for this test.
+{
+public:
+ Options (void);
+ // Constructor.
+
+ ~Options (void);
+ // Destructor.
+
+ int parse_args (int argc, ACE_TCHAR *argv[]);
+ // Parse the command-line arguments.
+
+ const ACE_Time_Value &sleep_time (void) const;
+ // Return the amount of time to sleep in order to implement the
+ // proper transmission rates.
+
+ u_short port (void) const;
+ // Port of the server.
+
+ const ACE_TCHAR *host (void) const;
+ // Host of the server.
+
+ size_t threads (void) const;
+ // Number of threads.
+
+ const char *quit_string (void) const;
+ // String that shuts down the client/server.
+
+ ssize_t read (void *buf, size_t len, size_t &iterations);
+ // Read from the appropriate location.
+
+ size_t message_len (void) const;
+ // Returns the length of the message to send.
+
+ const void *message_buf (void) const;
+ // Returns a pointer to the message.
+
+ ACE_THR_FUNC thr_func (void);
+ // Returns a pointer to the entry point into the thread that runs
+ // the client test function.
+
+private:
+ int init (void);
+ // Initialize the message we're sending to the user and set up the
+ // barrier.
+
+ char *shared_client_test (u_short port,
+ ACE_SSL_SOCK_Stream &cli_stream);
+ // Performs the shared behavior of the oneway and twoway client
+ // tests.
+
+ static void *twoway_client_test (void *);
+ // Performs the twoway test.
+
+ static void *oneway_client_test (void *);
+ // Performs the oneway test.
+
+ const ACE_TCHAR *host_;
+ // Host of the server.
+
+ u_short port_;
+ // Port of the server.
+
+ ACE_Time_Value sleep_time_;
+ // Sleep_Time value.
+
+ size_t threads_;
+ // Number of threads.
+
+ enum {QUIT_STRING_SIZE = 128};
+ char quit_string_[QUIT_STRING_SIZE];
+ // String that shuts down the client/server.
+
+ size_t message_len_;
+ // Size of the message we send to the server.
+
+ char *message_buf_;
+ // Pointer to the message we send to the server.
+
+ ACE_HANDLE io_source_;
+ // Are we reading I/O from ACE_STDIN or from our generator?
+
+ size_t iterations_;
+ // Number of iterations.
+
+ char oneway_;
+ // Are we running oneway or twoway?
+
+ // Please leave the ; inside the parenthesis to avoid Green Hills
+ // (and probably other) compiler warning about extra ;.
+ ACE_MT (ACE_Barrier *barrier_;)
+ // Barrier used to synchronize the start of all the threads.
+};
+
+#endif /* __ACE_SSL_CLIENT_H */
diff --git a/ACE/examples/IPC_SAP/SSL_SAP/SSL-server-fancy.cpp b/ACE/examples/IPC_SAP/SSL_SAP/SSL-server-fancy.cpp
new file mode 100644
index 00000000000..e2d2c8ad0c1
--- /dev/null
+++ b/ACE/examples/IPC_SAP/SSL_SAP/SSL-server-fancy.cpp
@@ -0,0 +1,606 @@
+// $Id$
+
+// This example tests the features of the <ACE_SSL_SOCK_Acceptor>,
+// <ACE_SSL_SOCK_Stream>, and <ACE_Svc_Handler> classes. If the platform
+// supports threads it uses a thread-per-connection concurrency model.
+// Otherwise, it uses a single-threaded iterative server model.
+
+#include "ace/Svc_Handler.h"
+#include "ace/Singleton.h"
+#include "ace/Profile_Timer.h"
+#include "ace/Get_Opt.h"
+#include "ace/OS_NS_sys_select.h"
+
+#include "ace/SSL/SSL_SOCK_Acceptor.h"
+
+#include "SSL-server-fancy.h"
+
+ACE_RCSID (SSL_SAP,
+ SSL_server_fancy,
+ "$Id$")
+
+// Forward declaration.
+class Handler;
+
+class Handler_Factory
+{
+ // = TITLE
+ // Creates the oneway or twoway handlers.
+public:
+ Handler_Factory (void);
+ // Constructor.
+
+ ~Handler_Factory (void);
+ // Destructor.
+
+ int handle_events (void);
+ // Run the main event loop.
+
+private:
+ int init_acceptors (void);
+ // Initialize the acceptors.
+
+ int create_handler (ACE_SSL_SOCK_Acceptor &acceptor,
+ Handler *(*handler_factory) (ACE_SSL_SOCK_Stream *),
+ const char *handler_type);
+ // Factory that creates the right kind of <Handler>.
+
+ // = Factory functions.
+
+ static Handler *make_twoway_handler (ACE_SSL_SOCK_Stream *);
+ // Create a twoway handler.
+
+ static Handler *make_oneway_handler (ACE_SSL_SOCK_Stream *);
+ // Create a oneway handler.
+
+ ACE_SSL_SOCK_Acceptor twoway_acceptor_;
+ // Twoway acceptor factory.
+
+ ACE_SSL_SOCK_Acceptor oneway_acceptor_;
+ // Oneway acceptor factory.
+};
+
+class Handler : public ACE_Svc_Handler<ACE_SSL_SOCK_STREAM, ACE_NULL_SYNCH>
+{
+ // = TITLE
+ // Base class for the oneway and twoway handlers.
+
+ friend class Handler_Factory;
+ // The factory has special permission. (to access svc ()).
+
+public:
+ virtual int open (void * = 0);
+ // Generic initialization method.
+
+ virtual int close (u_long);
+ // Close down and delete this.
+
+protected:
+
+ Handler (ACE_SSL_SOCK_Stream *ssl_stream);
+ // Constructor.
+
+ int parse_header_and_allocate_buffer (char *&buf,
+ ACE_INT32 *len);
+ // Implement the generic code that's called from any of the subclass
+ // <run> methods to get the header and the buffer to read the data.
+ // This method factors out common code.
+
+ virtual int run (void) = 0;
+ // Hook method called by the <svc> template method to do the actual
+ // protocol. Must be overridden by the subclass.
+
+ virtual int svc (void);
+ // Template method entry point into the handler task.
+
+ virtual void print_results (void);
+ // Print the results.
+
+ size_t total_bytes_;
+ // Total number of bytes received.
+
+ size_t message_count_;
+ // Number of messages received.
+
+ ACE_Profile_Timer timer_;
+ // Keeps track of how much time we're using.
+
+ ACE_SSL_SOCK_Stream *ssl_stream_;
+ //keep state information for a ssl_stream.
+};
+
+class Twoway_Handler : public Handler
+{
+ // = TITLE
+ // Performs the twoway protocol.
+public:
+
+ Twoway_Handler (ACE_SSL_SOCK_Stream *ssl_stream);
+ // Constructor.
+
+private:
+
+ virtual int run (void);
+ // Template Method hook called by <svc>.
+
+};
+
+class Oneway_Handler : public Handler
+{
+ // = TITLE
+public:
+ Oneway_Handler (ACE_SSL_SOCK_Stream *ssl_stream);
+ // Constructor.
+
+private:
+ virtual int run (void);
+ // Template Method hook called by <svc>.
+
+ virtual void print_results (void);
+ // Print the results.
+};
+
+u_short
+Options::port (void) const
+{
+ return this->port_;
+}
+
+int
+Options::verbose (void) const
+{
+ return this->verbose_;
+}
+
+int
+Options::reply_message_len (void) const
+{
+ return this->reply_message_len_;
+}
+
+Options::~Options (void)
+{
+}
+
+Options::Options (void)
+ : verbose_ (0),
+ port_ (ACE_DEFAULT_SERVER_PORT),
+ reply_message_len_ (24) // Default to the approximate size of an
+ // GIOP reply message.
+{
+}
+
+int
+Options::parse_args (int argc, ACE_TCHAR *argv[])
+{
+ ACE_Get_Opt getopt (argc, argv, ACE_TEXT ("p:r:v"), 1);
+
+ for (int c; (c = getopt ()) != -1; )
+ switch (c)
+ {
+ case 'p':
+ this->port_ = ACE_OS::atoi (getopt.opt_arg ());
+ break;
+ case 'r':
+ this->reply_message_len_ = ACE_OS::atoi (getopt.opt_arg ());
+ break;
+ case 'v':
+ this->verbose_ = 1;
+ break;
+ default:
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("(%P|%t) usage: %n [-p <port>] [-v]")),
+ -1);
+ }
+
+ return 0;
+}
+
+// Options Singleton.
+typedef ACE_Singleton<Options, ACE_SYNCH_RECURSIVE_MUTEX> OPTIONS;
+
+Handler::Handler (ACE_SSL_SOCK_Stream *ssl_stream)
+ : total_bytes_ (0),
+ message_count_ (0),
+ ssl_stream_ (ssl_stream)
+
+{
+}
+
+int
+Handler::open (void *)
+{
+ ACE_INET_Addr cli_addr;
+
+ // Make sure we're not in non-blocking mode.
+ if (this->ssl_stream_-> disable (ACE_NONBLOCK) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("disable")),
+ 0);
+
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("(%P|%t) client %C connected from %d \n"),
+ cli_addr.get_host_name (),
+ cli_addr.get_port_number ()));
+
+ return 0;
+}
+
+int
+Handler::close (u_long)
+{
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("(%P|%t) closing down %@\n"),
+ this));
+
+ delete this->ssl_stream_;
+ delete this;
+
+ return 0;
+}
+
+int
+Handler::svc (void)
+{
+ // Timer logic.
+ this->timer_.start ();
+
+ // Invoke the hook method to run the specific test.
+ int result = this->run ();
+
+ this->timer_.stop ();
+
+ this->print_results ();
+
+ return result;
+}
+
+int
+Handler::parse_header_and_allocate_buffer (char *&request,
+ ACE_INT32 *len)
+{
+ ssize_t result = this->ssl_stream_ -> recv_n ((void *) len,
+ sizeof (ACE_INT32));
+ if (result == 0)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("(%P|%t) connected closed\n")));
+ return -1;
+ }
+ else if (result == -1 || result != sizeof (ACE_INT32))
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("(%P|%t) %p\n"),
+ ACE_TEXT ("recv_n failed")),
+ -1);
+ else
+ {
+ *len = ntohl (*len);
+ ACE_NEW_RETURN (request,
+ char[*len],
+ -1);
+ }
+
+ return 0;
+}
+
+void
+Handler::print_results (void)
+{
+}
+
+Twoway_Handler::Twoway_Handler (ACE_SSL_SOCK_Stream* ssl_stream)
+ : Handler (ssl_stream)
+{
+}
+
+// Function entry point into the twoway server task.
+
+int
+Twoway_Handler::run (void)
+{
+ // Read data from client (terminate on error).
+
+ char *request = 0;
+
+ for (;;)
+ {
+ ACE_INT32 len = 0;
+
+ if (parse_header_and_allocate_buffer (request,
+ &len) == -1)
+ return -1;
+
+ // Subtract off the sizeof the length prefix.
+ ssize_t r_bytes =
+ this->ssl_stream_ -> recv_n (request,
+ len - sizeof (ACE_UINT32));
+
+ if (r_bytes == -1)
+ {
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("recv")));
+ break;
+ }
+ else if (r_bytes == 0)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("(%P|%t) reached end of input, connection ")
+ ACE_TEXT ("closed by client\n")));
+ break;
+ }
+ else if (OPTIONS::instance ()->verbose ()
+ && ACE::write_n (ACE_STDOUT,
+ request,
+ r_bytes) != r_bytes)
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("ACE::write_n")));
+ else
+ {
+ ssize_t s_bytes =
+ (ssize_t) OPTIONS::instance ()->reply_message_len ();
+
+ // Don't try to send more than is in the request buffer!
+ if (s_bytes > r_bytes)
+ s_bytes = r_bytes;
+
+ if (this->ssl_stream_ -> send_n (request,
+ s_bytes) != s_bytes)
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("send_n")));
+ }
+ this->total_bytes_ += size_t (r_bytes);
+ this->message_count_++;
+
+ delete [] request;
+ request = 0;
+ }
+
+ delete [] request;
+ return 0;
+}
+
+Oneway_Handler::Oneway_Handler (ACE_SSL_SOCK_Stream *ssl_stream)
+ : Handler (ssl_stream)
+{
+}
+
+void
+Oneway_Handler::print_results (void)
+{
+ ACE_Profile_Timer::ACE_Elapsed_Time et;
+ this->timer_.elapsed_time (et);
+
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("\t\treal time = %f secs \n\t\tuser time = %f secs \n\t\tsystem time = %f secs\n"),
+ et.real_time,
+ et.user_time,
+ et.system_time));
+
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("\t\tmessages = %d\n\t\ttotal bytes = %d\n\t\tmbits/sec = %f\n\t\tusec-per-message = %f\n"),
+ this->message_count_,
+ this->total_bytes_,
+ (((double) this->total_bytes_ * 8) / et.real_time) / (double) (1024 * 1024),
+ ((et.user_time + et.system_time) / (double) this->message_count_) * ACE_ONE_SECOND_IN_USECS));
+}
+
+// Function entry point into the oneway server task.
+
+int
+Oneway_Handler::run (void)
+{
+ // Read data from client (terminate on error).
+
+ char *request = 0;
+
+ for (;;)
+ {
+ ACE_INT32 len = 0;
+
+ if (parse_header_and_allocate_buffer (request,
+ &len) == -1)
+ return -1;
+
+ // Subtract off the sizeof the length prefix.
+ ssize_t r_bytes =
+ this->ssl_stream_ -> recv_n (request,
+ len - sizeof (ACE_UINT32));
+
+ if (r_bytes == -1)
+ {
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("recv")));
+ break;
+ }
+ else if (r_bytes == 0)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("(%P|%t) reached end of input, connection ")
+ ACE_TEXT ("closed by client\n")));
+ break;
+ }
+ else if (OPTIONS::instance ()->verbose ()
+ && ACE::write_n (ACE_STDOUT,
+ request,
+ r_bytes) != r_bytes)
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("ACE::write_n")));
+
+ this->total_bytes_ += size_t (r_bytes);
+ this->message_count_++;
+ delete [] request;
+ request = 0;
+ }
+
+ delete [] request;
+ return 0;
+}
+
+// Create a twoway handler.
+
+Handler *
+Handler_Factory::make_twoway_handler (ACE_SSL_SOCK_Stream *ssl_stream)
+{
+ return new Twoway_Handler (ssl_stream);
+}
+
+// Create a oneway handler.
+
+Handler *
+Handler_Factory::make_oneway_handler (ACE_SSL_SOCK_Stream *ssl_stream)
+
+{
+ return new Oneway_Handler (ssl_stream);
+}
+
+int
+Handler_Factory::init_acceptors (void)
+{
+ // Create the oneway and twoway server addresses.
+ ACE_INET_Addr twoway_server_addr (OPTIONS::instance ()->port ());
+ ACE_INET_Addr oneway_server_addr (OPTIONS::instance ()->port () + 1);
+
+ // Create acceptors, reuse the address.
+ if (this->twoway_acceptor_.open (twoway_server_addr, 1) == -1
+ || this->oneway_acceptor_.open (oneway_server_addr, 1) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("open")),
+ -1);
+ else if (this->twoway_acceptor_.get_local_addr (twoway_server_addr) == -1
+ || this->oneway_acceptor_.get_local_addr (oneway_server_addr) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("get_local_addr")),
+ -1);
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("(%P|%t) starting twoway server at port %d and oneway server at port %d\n"),
+ twoway_server_addr.get_port_number (),
+ oneway_server_addr.get_port_number ()));
+ return 0;
+}
+
+int
+Handler_Factory::create_handler (
+ ACE_SSL_SOCK_Acceptor &acceptor,
+ Handler * (*handler_factory) (ACE_SSL_SOCK_Stream* ),
+ const char *handler_type)
+{
+ ACE_SSL_SOCK_Stream* new_stream;
+
+ ACE_NEW_RETURN (new_stream, ACE_SSL_SOCK_Stream, -1);
+
+ if (acceptor.accept (*new_stream) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("accept")),
+ -1);
+
+ Handler *handler;
+
+ ACE_ALLOCATOR_RETURN (handler,
+ (*handler_factory) (new_stream),
+ -1);
+
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("(%P|%t) spawning %s handler\n"),
+ handler_type));
+
+ if (handler->open () == -1)
+ return -1;
+
+#if defined (ACE_MT_SAFE)
+ // Spawn a new thread and run the new connection in that thread of
+ // control using the <server> function as the entry point.
+ return handler->activate ();
+#else
+ handler->svc ();
+ handler->close (0);
+ return 0;
+#endif /* ACE_HAS_THREADS */
+}
+
+Handler_Factory::Handler_Factory (void)
+{
+}
+
+Handler_Factory::~Handler_Factory (void)
+{
+ this->twoway_acceptor_.close ();
+ this->oneway_acceptor_.close ();
+}
+
+// Run the main event loop.
+
+int
+Handler_Factory::handle_events (void)
+{
+ if (this->init_acceptors () == -1)
+ return -1;
+
+ fd_set handles;
+
+ FD_ZERO (&handles);
+ FD_SET ((ACE_SOCKET) this->twoway_acceptor_.get_handle (), &handles);
+ FD_SET ((ACE_SOCKET) this->oneway_acceptor_.get_handle (), &handles);
+
+ // Performs the iterative server activities.
+
+ for (;;)
+ {
+ ACE_Time_Value timeout (ACE_DEFAULT_TIMEOUT);
+ fd_set temp = handles;
+
+ int result =
+ ACE_OS::select (int (this->oneway_acceptor_.get_handle ()) + 1,
+ (fd_set *) &temp,
+ 0,
+ 0,
+ timeout);
+ if (result == -1)
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("(%P|%t) %p\n"),
+ ACE_TEXT ("select")));
+ else if (result == 0 && OPTIONS::instance ()->verbose ())
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("(%P|%t) select timed out\n")));
+ else
+ {
+ if (FD_ISSET (this->twoway_acceptor_.get_handle (),
+ &temp))
+ this->create_handler (this->twoway_acceptor_,
+ &Handler_Factory::make_twoway_handler,
+ "twoway");
+ if (FD_ISSET (this->oneway_acceptor_.get_handle (),
+ &temp))
+ this->create_handler (this->oneway_acceptor_,
+ &Handler_Factory::make_oneway_handler,
+ "oneway");
+ }
+ }
+
+ ACE_NOTREACHED (return 0;)
+}
+
+int
+ACE_TMAIN (int argc, ACE_TCHAR *argv[])
+{
+
+ ACE_SSL_Context *context = ACE_SSL_Context::instance ();
+
+ context->certificate ("./dummy.pem", SSL_FILETYPE_PEM);
+ context->private_key ("./key.pem", SSL_FILETYPE_PEM);
+
+ OPTIONS::instance ()->parse_args (argc, argv);
+
+ Handler_Factory server;
+
+ return server.handle_events ();
+}
+
diff --git a/ACE/examples/IPC_SAP/SSL_SAP/SSL-server-fancy.h b/ACE/examples/IPC_SAP/SSL_SAP/SSL-server-fancy.h
new file mode 100644
index 00000000000..fed1b513f90
--- /dev/null
+++ b/ACE/examples/IPC_SAP/SSL_SAP/SSL-server-fancy.h
@@ -0,0 +1,44 @@
+// -*- C++ -*-
+// $Id$
+
+// This file defines the Options class for SSL-server-fancy.
+// IBM C++ compiler'd template auto-instantiator needs this in a separate file.
+
+#ifndef __ACE_SSL_SERVER_FANCY_H
+#define __ACE_SSL_SERVER_FANCY_H
+
+class Options
+ // = TITLE
+ // Define the options for this test.
+{
+public:
+ Options (void);
+ // Constructor.
+
+ ~Options (void);
+ // Destructor.
+
+ int parse_args (int argc, ACE_TCHAR *argv[]);
+ // Parse the command-line arguments.
+
+ int verbose (void) const;
+ // Are we running in verbose mode?
+
+ u_short port (void) const;
+ // Port number that we are listening at.
+
+ int reply_message_len (void) const;
+ // Size of the reply message.
+
+private:
+ int verbose_;
+ // Are we running in verbose mode?
+
+ u_short port_;
+ // Port number we listen at.
+
+ size_t reply_message_len_;
+ // Size of the reply message.
+};
+
+#endif /* __ACE_SSL_SERVER_FANCY_H */
diff --git a/ACE/examples/IPC_SAP/SSL_SAP/SSL-server-poll.cpp b/ACE/examples/IPC_SAP/SSL_SAP/SSL-server-poll.cpp
new file mode 100644
index 00000000000..83333ccc357
--- /dev/null
+++ b/ACE/examples/IPC_SAP/SSL_SAP/SSL-server-poll.cpp
@@ -0,0 +1,212 @@
+// $Id$
+
+// IPC_SAP/poll server, which illustrates how to integrate the ACE
+// SSL socket wrappers with the SVR4 <poll> system call to create a
+// single-threaded concurrent server. This server program can be
+// driven by the oneway test mode of SSL-client.cpp.
+
+#include "ace/OS_NS_stdlib.h"
+#include "ace/OS_NS_unistd.h"
+#include "ace/Time_Value.h"
+#include "ace/SSL/SSL_SOCK_Acceptor.h"
+
+ACE_RCSID (SSL_SAP,
+ SSL_server_poll,
+ "$Id$")
+
+#if defined (ACE_HAS_POLL)
+
+#include "ace/SSL/SSL_SOCK_Stream.h"
+
+#include "ace/Log_Msg.h"
+#include "ace/INET_Addr.h"
+#include "ace/OS_NS_stdio.h"
+#include "ace/OS_NS_poll.h"
+
+
+// Should we be verbose?
+static int verbose = 0;
+
+// Max number of open handles.
+static const int MAX_HANDLES = 200;
+
+struct Buffer_Info
+{
+ void *buf_;
+ // Pointer to the buffer.
+
+ size_t len_;
+ // Length of the buffer.
+};
+
+// Array of <pollfd>'s.
+static struct pollfd poll_array[MAX_HANDLES];
+
+// Array of <Buffer_Info>.
+static Buffer_Info buffer_array[MAX_HANDLES];
+
+static void
+init_poll_array (void)
+{
+ int i;
+
+ for (i = 0; i < MAX_HANDLES; i++)
+ {
+ poll_array[i].fd = ACE_INVALID_HANDLE;
+ poll_array[i].events = POLLIN;
+ }
+}
+
+static int
+init_buffer (size_t index)
+{
+ ACE_INT32 len;
+
+ if (ACE::recv_n (poll_array[index].fd,
+ (void *) &len,
+ sizeof (ACE_INT32)) != sizeof (ACE_INT32))
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "(%P|%t) %p\n",
+ "recv_n failed"),
+ -1);
+ else
+ {
+ len = ntohl (len);
+ ACE_DEBUG ((LM_DEBUG,
+ "(%P|%t) reading messages of size %d from handle %d\n",
+ len,
+ poll_array[index].fd));
+
+ ACE_ALLOCATOR_RETURN (buffer_array[index].buf_,
+ ACE_OS::malloc (len),
+ -1);
+ buffer_array[index].len_ = len;
+ }
+ return 0;
+}
+
+static void
+handle_data (size_t &n_handles)
+{
+ // Handle pending logging messages first (s_handle + 1 is guaranteed
+ // to be lowest client descriptor).
+
+ for (size_t index = 1; index < n_handles; index++)
+ {
+ if (ACE_BIT_ENABLED (poll_array[index].revents, POLLIN))
+ {
+ // First time in, we need to initialize the buffer.
+ if (buffer_array[index].buf_ == 0
+ && init_buffer (index) == -1)
+ {
+ ACE_ERROR ((LM_ERROR,
+ "(%P|%t) %p\n",
+ "init_buffer"));
+ continue;
+ }
+
+ // Read data from client (terminate on error).
+
+ ssize_t n = ACE::recv (poll_array[index].fd,
+ buffer_array[index].buf_,
+ buffer_array[index].len_);
+ // <recv> will not block in this case!
+
+ if (n == -1)
+ ACE_ERROR ((LM_ERROR,
+ "%p\n",
+ "read failed"));
+ else if (n == 0)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ "(%P|%t) closing oneway server at handle %d\n",
+ poll_array[index].fd));
+
+ // Handle client connection shutdown.
+ ACE_OS::close (poll_array[index].fd);
+ poll_array[index].fd = poll_array[--n_handles].fd;
+
+ ACE_OS::free ((void *) buffer_array[index].buf_);
+ buffer_array[index].buf_ = 0;
+ buffer_array[index].len_ = 0;
+ }
+ else if (verbose)
+ ACE_DEBUG ((LM_DEBUG,
+ "(%P|%t) %*s",
+ n,
+ buffer_array[index].buf_));
+ }
+ }
+}
+
+static void
+handle_connections (ACE_SSL_SOCK_Acceptor &peer_acceptor,
+ size_t &n_handles)
+{
+ if (ACE_BIT_ENABLED (poll_array[0].revents, POLLIN))
+ {
+ ACE_SSL_SOCK_Stream new_stream;
+
+ ACE_INET_Addr client;
+ ACE_Time_Value nonblock (0, 0);
+
+ // Handle all pending connection requests (note use of "polling"
+ // feature that doesn't block).
+
+ while (ACE_OS::poll (poll_array, 1, nonblock) > 0)
+ if (peer_acceptor.accept (new_stream, &client) == -1)
+ ACE_OS::perror ("accept");
+ else
+ {
+ const char *s = client.get_host_name ();
+
+ ACE_ASSERT (s != 0);
+ ACE_DEBUG ((LM_DEBUG,
+ "(%P|%t) client %s\n",
+ s));
+ poll_array[n_handles++].fd = new_stream.get_handle ();
+ }
+ }
+}
+
+int
+main (int, char *[])
+{
+ u_short port = ACE_DEFAULT_SERVER_PORT + 1;
+
+ // Create a server end-point.
+ ACE_INET_Addr addr (port);
+ ACE_SSL_SOCK_Acceptor peer_acceptor (addr);
+
+ ACE_HANDLE s_handle = peer_acceptor.get_handle ();
+
+ init_poll_array ();
+
+ poll_array[0].fd = s_handle;
+
+ ACE_DEBUG ((LM_DEBUG,
+ "(%P|%t) starting oneway server at port %d\n",
+ port));
+
+ for (size_t n_handles = 1;;)
+ {
+ // Wait for client I/O events (handle interrupts).
+ while (ACE_OS::poll (poll_array, n_handles) == -1
+ && errno == EINTR)
+ continue;
+
+ handle_data (n_handles);
+ handle_connections (peer_acceptor, n_handles);
+ }
+
+ /* NOTREACHED */
+ return 0;
+}
+#else
+#include "ace/OS_NS_stdio.h"
+int main (int, char *[])
+{
+ ACE_OS::fprintf (stderr, "This feature is not supported\n");
+ return 0;
+}
+#endif /* ACE_HAS_POLL */
diff --git a/ACE/examples/IPC_SAP/SSL_SAP/SSL-server-simple.cpp b/ACE/examples/IPC_SAP/SSL_SAP/SSL-server-simple.cpp
new file mode 100644
index 00000000000..22535160cf0
--- /dev/null
+++ b/ACE/examples/IPC_SAP/SSL_SAP/SSL-server-simple.cpp
@@ -0,0 +1,366 @@
+// $Id$
+
+// This example tests the features of the <ACE_SSL_SOCK_Acceptor>,
+// <ACE_SSL_SOCK_Stream>, and <ACE_Svc_Handler> classes.
+
+#include "ace/Thread_Manager.h"
+#include "ace/Handle_Set.h"
+#include "ace/Profile_Timer.h"
+#include "ace/OS_NS_sys_select.h"
+
+#include "ace/SSL/SSL_SOCK_Acceptor.h"
+
+ACE_RCSID(SSL_SAP, SSL_server_simple, "$Id$")
+
+// Are we running verbosely?
+static int verbose = 1;
+
+// Function entry point into the twoway server task.
+
+int
+twoway_server (ACE_SSL_SOCK_Stream &stream)
+{
+ ACE_INET_Addr cli_addr;
+
+ // Make sure we're not in non-blocking mode.
+ if (stream.disable (ACE_NONBLOCK) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%p\n",
+ "disable"),
+ 0);
+ else if (stream.get_remote_addr (cli_addr) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%p\n",
+ "get_remote_addr"),
+ 0);
+
+ ACE_DEBUG ((LM_DEBUG,
+ "(%P|%t) client %s connected from %d\n",
+ cli_addr.get_host_name (),
+ cli_addr.get_port_number ()));
+
+ size_t total_bytes = 0;
+ size_t message_count = 0;
+
+ char *request = 0;
+
+ // Read data from client (terminate on error).
+
+ for (;;)
+ {
+ ACE_INT32 len;
+
+ ssize_t r_bytes = stream.recv_n ((void *) &len,
+ sizeof (ACE_INT32));
+ if (r_bytes == -1)
+ {
+ ACE_ERROR ((LM_ERROR,
+ "%p\n",
+ "recv"));
+ break;
+ }
+ else if (r_bytes == 0)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ "(%P|%t) reached end of input, connection closed by client\n"));
+ break;
+ }
+ else if (r_bytes != sizeof (ACE_INT32))
+ {
+ ACE_ERROR ((LM_ERROR,
+ "(%P|%t) %p\n",
+ "recv_n failed"));
+ break;
+ }
+ else
+ {
+ len = ntohl (len);
+ ACE_NEW_RETURN (request,
+ char [len],
+ 0);
+ }
+
+ // Subtract off the sizeof the length prefix.
+ r_bytes = stream.recv_n (request,
+ len - sizeof (ACE_UINT32));
+ if (r_bytes == -1)
+ {
+ ACE_ERROR ((LM_ERROR,
+ "%p\n",
+ "recv"));
+ break;
+ }
+ else if (r_bytes == 0)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ "(%P|%t) reached end of input, connection closed by client\n"));
+ break;
+ }
+ else if (verbose
+ && ACE::write_n (ACE_STDOUT,
+ request,
+ r_bytes) != r_bytes)
+ ACE_ERROR ((LM_ERROR,
+ "%p\n",
+ "ACE::write_n"));
+ else if (stream.send_n (request,
+ r_bytes) != r_bytes)
+ ACE_ERROR ((LM_ERROR,
+ "%p\n",
+ "send_n"));
+
+ total_bytes += size_t (r_bytes);
+ message_count++;
+
+ delete [] request;
+ request = 0;
+ }
+
+ // Close new endpoint (listening endpoint stays open).
+ stream.close ();
+
+ delete [] request;
+ return 0;
+}
+
+// Function entry point into the oneway server task.
+
+static int
+oneway_server (ACE_SSL_SOCK_Stream &stream)
+{
+ ACE_INET_Addr cli_addr;
+
+ // Make sure we're not in non-blocking mode.
+ if (stream.disable (ACE_NONBLOCK) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%p\n",
+ "disable"),
+ 0);
+ else if (stream.get_remote_addr (cli_addr) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%p\n",
+ "get_remote_addr"),
+ 0);
+
+ ACE_DEBUG ((LM_DEBUG,
+ "(%P|%t) client %s connected from %d\n",
+ cli_addr.get_host_name (),
+ cli_addr.get_port_number ()));
+
+ // Timer business
+ ACE_Profile_Timer timer;
+ timer.start ();
+
+ size_t total_bytes = 0;
+ size_t message_count = 0;
+
+ char *request = 0;
+
+ // Read data from client (terminate on error).
+
+ for (;;)
+ {
+ ACE_INT32 len;
+
+ ssize_t r_bytes = stream.recv_n ((void *) &len,
+ sizeof (ACE_INT32));
+ if (r_bytes == -1)
+ {
+ ACE_ERROR ((LM_ERROR,
+ "%p\n",
+ "recv"));
+ break;
+ }
+ else if (r_bytes == 0)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ "(%P|%t) reached end of input, connection closed by client\n"));
+ break;
+ }
+ else if (r_bytes != sizeof (ACE_INT32))
+ {
+ ACE_ERROR ((LM_ERROR,
+ "(%P|%t) %p\n",
+ "recv_n failed"));
+ break;
+ }
+ else
+ {
+ len = ntohl (len);
+ ACE_NEW_RETURN (request,
+ char [len],
+ 0);
+ }
+
+ // Subtract off the sizeof the length prefix.
+ r_bytes = stream.recv_n (request,
+ len - sizeof (ACE_UINT32));
+
+ if (r_bytes == -1)
+ {
+ ACE_ERROR ((LM_ERROR,
+ "%p\n",
+ "recv"));
+ break;
+ }
+ else if (r_bytes == 0)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ "(%P|%t) reached end of input, connection closed by client\n"));
+ break;
+ }
+ else if (verbose
+ && ACE::write_n (ACE_STDOUT, request, r_bytes) != r_bytes)
+ ACE_ERROR ((LM_ERROR,
+ "%p\n",
+ "ACE::write_n"));
+
+ total_bytes += size_t (r_bytes);
+ message_count++;
+
+ delete [] request;
+ request = 0;
+ }
+
+ timer.stop ();
+
+ ACE_Profile_Timer::ACE_Elapsed_Time et;
+ timer.elapsed_time (et);
+
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("\t\treal time = %f secs \n\t\tuser time = %f secs \n\t\tsystem time = %f secs\n"),
+ et.real_time,
+ et.user_time,
+ et.system_time));
+
+ double messages_per_sec = double (message_count) / et.real_time;
+
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("\t\tmessages = %d\n\t\ttotal bytes = %d\n\t\tmbits/sec = %f\n\t\tusec-per-message = %f\n\t\tmessages-per-second = %0.00f\n"),
+ message_count,
+ total_bytes,
+ (((double) total_bytes * 8) / et.real_time) / (double) (1024 * 1024),
+ (et.real_time / (double) message_count) * 1000000,
+ messages_per_sec < 0 ? 0 : messages_per_sec));
+
+ // Close new endpoint (listening endpoint stays open).
+ stream.close ();
+
+ delete [] request;
+ return 0;
+}
+
+static int
+run_event_loop (u_short port)
+{
+ // Raise the socket handle limit to the maximum.
+ ACE::set_handle_limit ();
+
+ // Create the oneway and twoway acceptors.
+ ACE_SSL_SOCK_Acceptor twoway_acceptor;
+ ACE_SSL_SOCK_Acceptor oneway_acceptor;
+
+ // Create the oneway and twoway server addresses.
+ ACE_INET_Addr twoway_server_addr (port);
+ ACE_INET_Addr oneway_server_addr (port + 1);
+
+ // Create acceptors, reuse the address.
+ if (twoway_acceptor.open (twoway_server_addr, 1) == -1
+ || oneway_acceptor.open (oneway_server_addr, 1) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%p\n",
+ "open"),
+ 1);
+ else if (twoway_acceptor.get_local_addr (twoway_server_addr) == -1
+ || oneway_acceptor.get_local_addr (oneway_server_addr) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%p\n",
+ "get_local_addr"),
+ 1);
+
+ ACE_DEBUG ((LM_DEBUG,
+ "(%P|%t) starting twoway server at port %d and oneway server at port %d\n",
+ twoway_server_addr.get_port_number (),
+ oneway_server_addr.get_port_number ()));
+
+ // Keep these objects out here to prevent excessive constructor
+ // calls within the loop.
+ ACE_SSL_SOCK_Stream new_stream;
+
+ ACE_Handle_Set handle_set;
+ handle_set.set_bit (twoway_acceptor.get_handle ());
+ handle_set.set_bit (oneway_acceptor.get_handle ());
+
+ // Performs the iterative server activities.
+
+ for (;;)
+ {
+ ACE_Time_Value timeout (ACE_DEFAULT_TIMEOUT);
+ ACE_Handle_Set temp = handle_set;
+
+ int maxfd = int(oneway_acceptor.get_handle ());
+ if (maxfd < int(twoway_acceptor.get_handle ()))
+ maxfd = int(twoway_acceptor.get_handle ());
+ int result = ACE_OS::select (maxfd + 1,
+ (fd_set *) temp,
+ 0,
+ 0,
+ timeout);
+ if (result == -1)
+ ACE_ERROR ((LM_ERROR,
+ "(%P|%t) %p\n",
+ "select"));
+ else if (result == 0 && verbose)
+ ACE_DEBUG ((LM_DEBUG,
+ "(%P|%t) select timed out\n"));
+ else
+ {
+ if (temp.is_set (twoway_acceptor.get_handle ()))
+ {
+ int r = twoway_acceptor.accept (new_stream);
+ while (r == -1 && errno == EAGAIN)
+ r = twoway_acceptor.accept (new_stream);
+ if (r == -1)
+ {
+ ACE_ERROR ((LM_ERROR,
+ "%p\n",
+ "accept"));
+ continue;
+ }
+ else
+ ACE_DEBUG ((LM_DEBUG,
+ "(%P|%t) spawning twoway server\n"));
+
+ // Run the twoway server.
+ twoway_server (new_stream);
+ }
+ if (temp.is_set (oneway_acceptor.get_handle ()))
+ {
+ if (oneway_acceptor.accept (new_stream) == -1)
+ {
+ ACE_ERROR ((LM_ERROR, "%p\n", "accept"));
+ continue;
+ }
+ else
+ ACE_DEBUG ((LM_DEBUG,
+ "(%P|%t) spawning oneway server\n"));
+
+ // Run the oneway server.
+ oneway_server (new_stream);
+ }
+ }
+ }
+
+ /* NOTREACHED */
+}
+
+int
+main (int argc, char *argv[])
+{
+ u_short port = ACE_DEFAULT_SERVER_PORT;
+
+ if (argc > 1)
+ port = ACE_OS::atoi (argv[1]);
+
+ return run_event_loop (port);
+}
diff --git a/ACE/examples/IPC_SAP/SSL_SAP/SSL-server.cpp b/ACE/examples/IPC_SAP/SSL_SAP/SSL-server.cpp
new file mode 100644
index 00000000000..8563067af03
--- /dev/null
+++ b/ACE/examples/IPC_SAP/SSL_SAP/SSL-server.cpp
@@ -0,0 +1,430 @@
+// $Id$
+
+// This example tests the features of the <ACE_SSL_SOCK_Acceptor>,
+// <ACE_SSL_SOCK_Stream>, and <ACE_Svc_Handler> classes. If the platform
+// supports threads it uses a thread-per-connection concurrency model.
+// Otherwise, it uses a single-threaded iterative server model.
+
+#include "ace/Thread_Manager.h"
+#include "ace/Handle_Set.h"
+#include "ace/Profile_Timer.h"
+#include "ace/OS_NS_sys_select.h"
+
+#include "ace/SSL/SSL_SOCK_Acceptor.h"
+
+ACE_RCSID(SSL_SAP, SSL_server, "$Id$")
+
+// Are we running verbosely?
+static int verbose = 0;
+
+static void
+run_server (ACE_THR_FUNC server,
+ ACE_SSL_SOCK_Stream * new_stream)
+{
+#if defined (ACE_HAS_THREADS)
+ // Spawn a new thread and run the new connection in that thread of
+ // control using the <server> function as the entry point.
+ if (ACE_Thread_Manager::instance ()->spawn (server,
+ (void *) new_stream,
+ THR_DETACHED) == -1)
+ ACE_ERROR ((LM_ERROR,
+ "(%P|%t) %p\n",
+ "spawn"));
+#else
+ (*server) ((void *) new_stream);
+#endif /* ACE_HAS_THREADS */
+}
+
+// Function entry point into the twoway server task.
+
+static ACE_THR_FUNC_RETURN
+twoway_server (void *arg)
+{
+ ACE_INET_Addr cli_addr;
+ ACE_SSL_SOCK_Stream * new_stream = (ACE_SSL_SOCK_Stream *) arg;
+
+ // Make sure we're not in non-blocking mode.
+ if (new_stream->disable (ACE_NONBLOCK) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%p\n",
+ "disable"),
+ 0);
+ else if (new_stream->get_remote_addr (cli_addr) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%p\n",
+ "get_remote_addr"),
+ 0);
+
+ ACE_DEBUG ((LM_DEBUG,
+ "(%P|%t) client %s connected from %d\n",
+ cli_addr.get_host_name (),
+ cli_addr.get_port_number ()));
+
+ size_t total_bytes = 0;
+ size_t message_count = 0;
+
+ char *request = 0;
+
+ // Read data from client (terminate on error).
+
+ for (;;)
+ {
+ ACE_INT32 len;
+
+ ssize_t r_bytes = new_stream->recv_n ((void *) &len,
+ sizeof (ACE_INT32));
+ if (r_bytes == -1)
+ {
+ ACE_ERROR ((LM_ERROR,
+ "%p\n",
+ "recv"));
+ break;
+ }
+ else if (r_bytes == 0)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ "(%P|%t) reached end of input, connection closed by client\n"));
+ break;
+ }
+ else if (r_bytes != sizeof (ACE_INT32))
+ {
+ ACE_ERROR ((LM_ERROR,
+ "(%P|%t) %p\n",
+ "recv_n failed"));
+ break;
+ }
+ else
+ {
+ len = ntohl (len);
+ ACE_NEW_RETURN (request,
+ char [len],
+ 0);
+ }
+
+ // Subtract off the sizeof the length prefix.
+ r_bytes = new_stream->recv_n (request,
+ len - sizeof (ACE_UINT32));
+ if (r_bytes == -1)
+ {
+ ACE_ERROR ((LM_ERROR,
+ "%p\n",
+ "recv"));
+ break;
+ }
+ else if (r_bytes == 0)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ "(%P|%t) reached end of input, "
+ "connection closed by client\n"));
+ break;
+ }
+ else if (verbose
+ && ACE::write_n (ACE_STDOUT,
+ request,
+ r_bytes) != r_bytes)
+ ACE_ERROR ((LM_ERROR,
+ "%p\n",
+ "ACE::write_n"));
+ else if (new_stream->send_n (request,
+ r_bytes) != r_bytes)
+ ACE_ERROR ((LM_ERROR,
+ "%p\n",
+ "send_n"));
+
+ total_bytes += size_t (r_bytes);
+ message_count++;
+
+ delete [] request;
+ request = 0;
+ }
+
+ // Close new endpoint (listening endpoint stays open).
+ new_stream->close ();
+
+ delete new_stream;
+
+ delete [] request;
+
+ return 0;
+}
+
+// Function entry point into the oneway server task.
+
+static ACE_THR_FUNC_RETURN
+oneway_server (void *arg)
+{
+ ACE_INET_Addr cli_addr;
+ ACE_SSL_SOCK_Stream * new_stream = (ACE_SSL_SOCK_Stream *) arg;
+
+ // Make sure we're not in non-blocking mode.
+ if (new_stream->disable (ACE_NONBLOCK) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%p\n",
+ "disable"),
+ 0);
+ else if (new_stream->get_remote_addr (cli_addr) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%p\n",
+ "get_remote_addr"),
+ 0);
+
+ ACE_DEBUG ((LM_DEBUG,
+ "(%P|%t) client %s connected from %d\n",
+ cli_addr.get_host_name (),
+ cli_addr.get_port_number ()));
+
+ // Timer business
+ ACE_Profile_Timer timer;
+ timer.start ();
+
+ size_t total_bytes = 0;
+ size_t message_count = 0;
+
+ char *request = 0;
+
+ // Read data from client (terminate on error).
+
+ for (;;)
+ {
+ ACE_INT32 len;
+
+ ssize_t r_bytes = new_stream->recv_n ((void *) &len,
+ sizeof (ACE_INT32));
+ if (r_bytes == -1)
+ {
+ ACE_ERROR ((LM_ERROR,
+ "%p\n",
+ "recv"));
+ break;
+ }
+ else if (r_bytes == 0)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ "(%P|%t) reached end of input, connection closed by client\n"));
+ break;
+ }
+ else if (r_bytes != sizeof (ACE_INT32))
+ {
+ ACE_ERROR ((LM_ERROR,
+ "(%P|%t) %p\n",
+ "recv_n failed"));
+ break;
+ }
+ else
+ {
+ len = ntohl (len);
+ ACE_NEW_RETURN (request,
+ char [len],
+ 0);
+ }
+
+ // Subtract off the sizeof the length prefix.
+ r_bytes = new_stream->recv_n (request,
+ len - sizeof (ACE_UINT32));
+
+ if (r_bytes == -1)
+ {
+ ACE_ERROR ((LM_ERROR,
+ "%p\n",
+ "recv"));
+ break;
+ }
+ else if (r_bytes == 0)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ "(%P|%t) reached end of input, connection closed by client\n"));
+ break;
+ }
+ else if (verbose
+ && ACE::write_n (ACE_STDOUT, request, r_bytes) != r_bytes)
+ ACE_ERROR ((LM_ERROR,
+ "%p\n",
+ "ACE::write_n"));
+
+ total_bytes += size_t (r_bytes);
+ message_count++;
+
+ delete [] request;
+ request = 0;
+ }
+
+ timer.stop ();
+
+ ACE_Profile_Timer::ACE_Elapsed_Time et;
+ timer.elapsed_time (et);
+
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("\t\treal time = %f secs \n")
+ ACE_TEXT ("\t\tuser time = %f secs \n")
+ ACE_TEXT ("\t\tsystem time = %f secs\n"),
+ et.real_time,
+ et.user_time,
+ et.system_time));
+
+ double messages_per_sec = double (message_count) / et.real_time;
+
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("\t\tmessages = %d\n")
+ ACE_TEXT ("\t\ttotal bytes = %d\n")
+ ACE_TEXT ("\t\tmbits/sec = %f\n")
+ ACE_TEXT ("\t\tusec-per-message = %f\n")
+ ACE_TEXT ("\t\tmessages-per-second = %0.00f\n"),
+ message_count,
+ total_bytes,
+ (((double) total_bytes * 8) / et.real_time) / (double) (1024 * 1024),
+ (et.real_time / (double) message_count) * 1000000,
+ messages_per_sec < 0 ? 0 : messages_per_sec));
+
+ // Close new endpoint (listening endpoint stays open).
+ new_stream->close ();
+
+ delete new_stream;
+
+ delete [] request;
+
+ return 0;
+}
+
+static int
+run_event_loop (u_short port)
+{
+ // Raise the socket handle limit to the maximum.
+ ACE::set_handle_limit ();
+
+ // Create the oneway and twoway acceptors.
+ ACE_SSL_SOCK_Acceptor twoway_acceptor;
+ ACE_SSL_SOCK_Acceptor oneway_acceptor;
+
+ // Create the oneway and twoway server addresses.
+ ACE_INET_Addr twoway_server_addr (port);
+ ACE_INET_Addr oneway_server_addr (port + 1);
+
+ // Create acceptors, reuse the address.
+ if (twoway_acceptor.open (twoway_server_addr, 1) == -1
+ || oneway_acceptor.open (oneway_server_addr, 1) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%p\n",
+ "open"),
+ 1);
+ else if (twoway_acceptor.get_local_addr (twoway_server_addr) == -1
+ || oneway_acceptor.get_local_addr (oneway_server_addr) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%p\n",
+ "get_local_addr"),
+ 1);
+
+ ACE_DEBUG ((LM_DEBUG,
+ "(%P|%t) starting twoway server at port %d and oneway server at port %d\n",
+ twoway_server_addr.get_port_number (),
+ oneway_server_addr.get_port_number ()));
+
+ // Keep these objects out here to prevent excessive constructor
+ // calls within the loop.
+
+ ACE_Handle_Set handle_set;
+ handle_set.set_bit (twoway_acceptor.get_handle ());
+ handle_set.set_bit (oneway_acceptor.get_handle ());
+
+ ACE_SSL_SOCK_Stream * new_stream = 0;
+
+ // Performs the iterative server activities.
+ for (;;)
+ {
+ ACE_Time_Value timeout (ACE_DEFAULT_TIMEOUT);
+ ACE_Handle_Set temp = handle_set;
+
+ int result = ACE_OS::select (int (oneway_acceptor.get_handle ()) + 1,
+ (fd_set *) temp,
+ 0,
+ 0,
+ timeout);
+ if (result == -1)
+ ACE_ERROR ((LM_ERROR,
+ "(%P|%t) %p\n",
+ "select"));
+ else if (result == 0 && verbose)
+ ACE_DEBUG ((LM_DEBUG,
+ "(%P|%t) select timed out\n"));
+ else
+ {
+ // A new ACE_SSL_SOCK_Stream must be initialized for each
+ // connection. However, it retains (SSL) state so simply
+ // initializing a new ACE_SSL_SOCK_Stream by passing it a
+ // handle isn't enough, nor is it allowed. Such a scheme is
+ // is sometimes done with the non-SSL aware
+ // ACE_SOCK_Stream. An ACE_SSL_SOCK_Stream should only be
+ // initialized by an ACE_SSL_SOCK_Acceptor (server side), or an
+ // ACE_SSL_SOCK_Connector (client side).
+ //
+ // It is also possible to copy or assign an
+ // ACE_SSL_SOCK_Stream since it implements both
+ // methods/operators. However, the user must ensure that
+ // the copy or assignment is atomic.
+
+ if (temp.is_set (twoway_acceptor.get_handle ()))
+ {
+ ACE_NEW_RETURN (new_stream,
+ ACE_SSL_SOCK_Stream,
+ -1);
+
+ if (twoway_acceptor.accept (*new_stream) == -1)
+ {
+ ACE_ERROR ((LM_ERROR,
+ "%p\n",
+ "accept"));
+
+ delete new_stream;
+
+ continue;
+ }
+ else
+ ACE_DEBUG ((LM_DEBUG,
+ "(%P|%t) spawning twoway server\n"));
+
+ // Run the twoway server.
+ run_server (twoway_server,
+ new_stream);
+ }
+ if (temp.is_set (oneway_acceptor.get_handle ()))
+ {
+ ACE_NEW_RETURN (new_stream,
+ ACE_SSL_SOCK_Stream,
+ -1);
+
+ if (oneway_acceptor.accept (*new_stream) == -1)
+ {
+ ACE_ERROR ((LM_ERROR, "%p\n", "accept"));
+
+ delete new_stream;
+
+ continue;
+ }
+ else
+ ACE_DEBUG ((LM_DEBUG,
+ "(%P|%t) spawning oneway server\n"));
+
+ // Run the oneway server.
+ run_server (oneway_server,
+ new_stream);
+ }
+ }
+ }
+
+ /* NOTREACHED */
+}
+
+int
+main (int argc, char *argv[])
+{
+ ACE_SSL_Context *context = ACE_SSL_Context::instance ();
+
+ context->certificate ("./dummy.pem", SSL_FILETYPE_PEM);
+ context->private_key ("./key.pem", SSL_FILETYPE_PEM);
+
+ u_short port = ACE_DEFAULT_SERVER_PORT;
+
+ if (argc > 1)
+ port = ACE_OS::atoi (argv[1]);
+
+ return run_event_loop (port);
+}
diff --git a/ACE/examples/IPC_SAP/SSL_SAP/SSL_SAP.mpc b/ACE/examples/IPC_SAP/SSL_SAP/SSL_SAP.mpc
new file mode 100644
index 00000000000..675f104f4dc
--- /dev/null
+++ b/ACE/examples/IPC_SAP/SSL_SAP/SSL_SAP.mpc
@@ -0,0 +1,44 @@
+// -*- MPC -*-
+// $Id$
+
+project(*client) : aceexe, ssl {
+ exename = client
+ Source_Files {
+ SSL-client.cpp
+ }
+}
+
+project(*client_simple) : aceexe, ssl {
+ exename = client-simple
+ Source_Files {
+ SSL-client-simple.cpp
+ }
+}
+
+project(*server) : aceexe, ssl {
+ exename = server
+ Source_Files {
+ SSL-server.cpp
+ }
+}
+
+project(*server_fancy) : aceexe, ssl {
+ exename = server-fancy
+ Source_Files {
+ SSL-server-fancy.cpp
+ }
+}
+
+project(*server_poll) : aceexe, ssl {
+ exename = server-poll
+ Source_Files {
+ SSL-server-poll.cpp
+ }
+}
+
+project(*server_simple) : aceexe, ssl {
+ exename = server-simple
+ Source_Files {
+ SSL-server-simple.cpp
+ }
+}
diff --git a/ACE/examples/IPC_SAP/SSL_SAP/dummy.pem b/ACE/examples/IPC_SAP/SSL_SAP/dummy.pem
new file mode 100644
index 00000000000..d631a33b956
--- /dev/null
+++ b/ACE/examples/IPC_SAP/SSL_SAP/dummy.pem
@@ -0,0 +1,15 @@
+-----BEGIN CERTIFICATE-----
+MIICaTCCAdICAQAwDQYJKoZIhvcNAQEEBQAwcjELMAkGA1UEBhMCVVMxCzAJBgNV
+BAgTAkNBMQ8wDQYDVQQHEwZJcnZpbmUxDDAKBgNVBAoTA09DSTEMMAoGA1UECxMD
+VEFPMREwDwYDVQQDEwhwcml5YW5rYTEWMBQGCSqGSIb3DQEJARYHcGdvbnRsYTAe
+Fw0wMTAzMjkwNDM4NDZaFw0wMTA0MjgwNDM4NDZaMIGHMQswCQYDVQQGEwJVUzEL
+MAkGA1UECBMCQ0ExDzANBgNVBAcTBklydmluZTEdMBsGA1UEChMUT2JqZWN0IENv
+bXB1dGluZyBJbmMxEDAOBgNVBAsTB09DSStUQU8xETAPBgNVBAMTCHByaXlhbmth
+MRYwFAYJKoZIhvcNAQkBFgdwZ29udGxhMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCB
+iQKBgQClC6z/bX1JHF1Hg06NCnBmsikEjViEdJFuqLOH3rXSGbm+2Eo+IO4dHlFS
+u6+Ntk4olBZTuf0DqzyEgrOiN7cnKXpxJzb1cwCmVkvDQISMygf4o66+CHtF8o8Z
+Sbi9F5u9W+MILaoCexEIVZqfHffcGxvm5O2MorBSQNka3NcC3wIDAQABMA0GCSqG
+SIb3DQEBBAUAA4GBADuKX6kllE2sNdQYMbSzt5C/lcpgcsK0BR6L01cQA95b5TvL
+HsKMeeeRj2npR4EPXY2gqgWTrKHZvf01aoKE5LuyzSQ+qfFMuEfo7+p9SYIuIrLD
+5+J0wOwN0R0YZAEY5gCAqRGw26dwWDai+PASPsx0YXV1y9jBB1FFtUFgrpR8
+-----END CERTIFICATE-----
diff --git a/ACE/examples/IPC_SAP/SSL_SAP/key.pem b/ACE/examples/IPC_SAP/SSL_SAP/key.pem
new file mode 100644
index 00000000000..54ff8f0f488
--- /dev/null
+++ b/ACE/examples/IPC_SAP/SSL_SAP/key.pem
@@ -0,0 +1,15 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIICXAIBAAKBgQClC6z/bX1JHF1Hg06NCnBmsikEjViEdJFuqLOH3rXSGbm+2Eo+
+IO4dHlFSu6+Ntk4olBZTuf0DqzyEgrOiN7cnKXpxJzb1cwCmVkvDQISMygf4o66+
+CHtF8o8ZSbi9F5u9W+MILaoCexEIVZqfHffcGxvm5O2MorBSQNka3NcC3wIDAQAB
+AoGALYq/PexUeewdwTH2ZuzOf0gCEYN/PW19A/ABOii2OzdmDcdZFTO5AMfw4Mdx
+dcUsY/4Y+xmDO5Pwqw/1yXleTDqvEKCgIEHN4NWnYYSiZOy3LBzQ8XaMZ7/2PCqc
+s4EtesuRB2kZ7PH2R1vJfyGIxZPaO5MOFbs3QFnpBUjqOmECQQDQCYgnBcshCEro
+gsrTjxtZiVHjmXEo0Uo2m4CBQW1PLJmmUXBzivGkVFfhjKULjwvso3BePfmzy9wP
+7YFjVXN9AkEAyxjBXi2kYCcXfGQiNuIrLkyVXeGR2YWnhzS2nL1TjNngmCBbnj48
+qvoqOUQgFK0AeTe/x7lb4Cf24ejWF5vmiwJALensorAkpKWv4qD7IrXy00/7QsAa
+uWd3eZXYRq6p8U9mmc5fgyCnNB1pR95CjsqDVza7FhGXipbzepBwffveAQJBAMKc
+mxYyqDMW4nNoxDxRJs17xxkpwAdvAiQWB/JTnQ737DX5s7EDtECl7PXo6NDHIhAF
+srigToCR6wl4gkYnNpcCQHmlfa9Duf3VJI/XeHE9ZU8vS4qgx0Ikfh01xCqWlsaq
+nPRmtfktt4P8gxlryZCEPpRs9l/XwQY6tnpHr5EmV2Y=
+-----END RSA PRIVATE KEY-----
diff --git a/ACE/examples/IPC_SAP/SSL_SAP/local_data b/ACE/examples/IPC_SAP/SSL_SAP/local_data
new file mode 100644
index 00000000000..c0119859a28
--- /dev/null
+++ b/ACE/examples/IPC_SAP/SSL_SAP/local_data
@@ -0,0 +1 @@
+I am Iron man!
diff --git a/ACE/examples/IPC_SAP/SSL_SAP/summarize b/ACE/examples/IPC_SAP/SSL_SAP/summarize
new file mode 100755
index 00000000000..ee8ffd2df25
--- /dev/null
+++ b/ACE/examples/IPC_SAP/SSL_SAP/summarize
@@ -0,0 +1,45 @@
+eval '(exit $?0)' && eval 'exec perl -w -S $0 ${1+"$@"}'
+ & eval 'exec perl -w -S $0 $argv:q'
+ if 0;
+
+# $Id$
+#
+# Summarizes results from a series of runs of run_test, with
+# different numbers of clients. Example usage:
+#
+# $ for i in 1 2 5 10 15 20 25 30 35 40 45 50; do ./run_test $i; done
+# $ ./summarize
+#
+# The first three lines above let this script run without specifying the
+# full path to perl, as long as it is in the user's PATH.
+# Taken from perlrun man page.
+
+@files = glob 'client-*.log';
+@total_threads = ();
+
+foreach $file (@files) {
+ my ($i);
+ ($i = $file) =~ s/client-(\d+).log/$1/;
+ push @total_threads, $i;
+}
+
+print "No.of threads\t\tAverage Latency\n\n";
+
+foreach $total_threads (sort {$a <=> $b} @total_threads) {
+ undef $high_latency;
+
+ $high_latency = 0;
+ open (FILE, "client-${total_threads}.log") ||
+ die "$0: unable to open \"client-${total_threads}.log\"\n";
+ while ($line = <FILE>) {
+ if ($line =~ /.*usec-per-message = ([\d\.]+)/)
+ {
+ $high_latency += $1 ;
+ $number++;
+ }
+ }
+ close FILE;
+
+ printf "%3d\t\t\t%8f\n",
+ $total_threads, $high_latency/$number;
+}
diff --git a/ACE/examples/IPC_SAP/TLI_SAP/.cvsignore b/ACE/examples/IPC_SAP/TLI_SAP/.cvsignore
new file mode 100644
index 00000000000..db59757e191
--- /dev/null
+++ b/ACE/examples/IPC_SAP/TLI_SAP/.cvsignore
@@ -0,0 +1,16 @@
+ATM-client
+ATM-client
+ATM-server
+ATM-server
+CPP-client
+CPP-client
+CPP-server
+CPP-server
+db-client
+db-client
+db-server
+db-server
+ftp-client
+ftp-client
+ftp-server
+ftp-server
diff --git a/ACE/examples/IPC_SAP/TLI_SAP/CPP-ATM-client.cpp b/ACE/examples/IPC_SAP/TLI_SAP/CPP-ATM-client.cpp
new file mode 100644
index 00000000000..6990763a8b0
--- /dev/null
+++ b/ACE/examples/IPC_SAP/TLI_SAP/CPP-ATM-client.cpp
@@ -0,0 +1,162 @@
+// $Id$
+
+#include "ace/TLI_Connector.h"
+#include "ace/ATM_QoS.h"
+#include "ace/ATM_Addr.h"
+#include "ace/Log_Msg.h"
+
+ACE_RCSID(TLI_SAP, CPP_ATM_client, "$Id$")
+
+#if defined (ACE_HAS_FORE_ATM_XTI)
+
+/* ACE_XTI/ATM Client */
+
+int main (int argc, char *argv[])
+{
+ if (argc < 2)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Usage: %s [-s selector] hostname [QoS in KB/sec]\n",
+ argv[0]),
+ 1);
+
+ unsigned char selector = ACE_ATM_Addr::DEFAULT_SELECTOR;
+ int selector_specified = 0;
+ extern int optind;
+ int opt;
+ while ((opt = ACE_OS::getopt (argc, argv, "s:?h")) != EOF)
+ {
+ switch(opt)
+ {
+ case 's':
+ selector = ACE_OS::atoi (optarg);
+ selector_specified = 1;
+ break;
+ case '?':
+ case 'h':
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Usage: %s hostname [-s selector] [QoS in KB/s]\n",
+ argv[0]),
+ 1);
+ } // switch
+ } // while getopt
+
+ const char *host = argv[optind];
+
+ int rate = (argc == 3) ? ACE_OS::atoi (argv[2]) :
+ (argc == 5) ? ACE_OS::atoi (argv[4]) : 0;
+ // The timeout really gets ignored since FORE's drivers don't work when
+ // ioctl or fcntl calls are made on the transport id/file descriptor
+ int timeout = ACE_DEFAULT_TIMEOUT;
+
+ char buf[BUFSIZ];
+
+ ACE_TLI_Stream cli_stream;
+
+ ACE_ATM_Addr remote_addr (host);
+ if (selector_specified)
+ remote_addr.set_selector(selector);
+ char hostname[MAXNAMELEN];
+ ACE_OS::hostname(hostname, MAXNAMELEN);
+ ACE_ATM_Addr local_addr (hostname);
+
+ // In order to construct connections options the file handle is
+ // needed. Therefore, we need to open the TLI_Stream before we
+ // construct the options.
+ if (cli_stream.open (ACE_XTI_ATM_DEVICE, O_RDWR, 0) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%p\n",
+ "open failed"),
+ 1);
+
+ ACE_DEBUG ((LM_DEBUG,
+ "starting non-blocking connect\n"));
+
+ // Initiate timed, non-blocking connection with server.
+ ACE_TLI_Connector con;
+
+ // Construct QoS options - currently FORE only supports bandwidth
+ ACE_ATM_QoS qos;
+ qos.set_rate(cli_stream.get_handle (),
+ rate,
+ ACE_ATM_QoS::OPT_FLAGS_CPID);
+
+ struct netbuf optbuf = qos.get_qos();
+// long optlen = 0;
+// char *options = remote_addr.construct_options (cli_stream.get_handle (),
+// rate,
+// ACE_ATM_Addr::OPT_FLAGS_CPID,
+// &optlen);
+// struct netbuf optbuf;
+// optbuf.len = optlen;
+// optbuf.buf = options;
+
+ // Not sure why but reuse_addr set to true/1 causes problems for
+ // FORE/XTI/ATM - this is now handled in ACE_TLI_Connector::connect()
+ if (con.connect (cli_stream,
+ remote_addr,
+ (ACE_Time_Value *) &ACE_Time_Value::zero,
+ local_addr,
+ 1,
+ O_RDWR,
+ 0,
+ ACE_XTI_ATM_DEVICE,
+ 0,
+ 1,
+ 0,
+ &optbuf) == -1)
+ {
+ if (errno != EWOULDBLOCK)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%p\n",
+ "connection failed"),
+ 1);
+
+ ACE_DEBUG ((LM_DEBUG,
+ "starting timed connect\n"));
+
+ // Check if non-blocking connection is in progress, and wait up
+ // to timeout seconds for it to complete.
+ ACE_Time_Value tv (timeout);
+
+ if (con.complete (cli_stream,
+ &remote_addr,
+ &tv) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%p\n",
+ "connection failed"),
+ 1);
+ else
+ ACE_DEBUG ((LM_DEBUG,
+ "connected to %s\n",
+ remote_addr.addr_to_string ()));
+ }
+
+ // Send data to server (correctly handles "incomplete writes").
+
+ for (int r_bytes;
+ (r_bytes = ACE_OS::read (ACE_STDIN, buf, sizeof buf)) > 0;
+ )
+ if (cli_stream.send_n (buf,
+ r_bytes,
+ 0) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%p\n",
+ "send_n"),
+ 1);
+
+ // Explicitly close the connection.
+ if (cli_stream.close () == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%p\n",
+ "close"),
+ -1);
+ return 0;
+}
+#else
+int ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "your platform isn't configured to support XTI/ATM\n"),
+ 1);
+}
+#endif /* ACE_HAS_TLI */
diff --git a/ACE/examples/IPC_SAP/TLI_SAP/CPP-ATM-server.cpp b/ACE/examples/IPC_SAP/TLI_SAP/CPP-ATM-server.cpp
new file mode 100644
index 00000000000..d4d3dec813c
--- /dev/null
+++ b/ACE/examples/IPC_SAP/TLI_SAP/CPP-ATM-server.cpp
@@ -0,0 +1,114 @@
+// $Id$
+
+#include "ace/TLI_Acceptor.h"
+#include "ace/ATM_Addr.h"
+#include "ace/Log_Msg.h"
+
+ACE_RCSID(TLI_SAP, CPP_ATM_server, "$Id$")
+
+#if defined (ACE_HAS_FORE_ATM_XTI)
+// ACE_TLI Server
+
+int
+main (int argc, char *argv[])
+{
+ ACE_Time_Value timeout (ACE_DEFAULT_TIMEOUT);
+
+ unsigned char selector = ACE_ATM_Addr::DEFAULT_SELECTOR;
+ int selector_specified = 0;
+ int opt;
+ while ((opt = ACE_OS::getopt (argc, argv, "s:?h")) != EOF)
+ {
+ switch(opt)
+ {
+ case 's':
+ selector = ACE_OS::atoi (optarg);
+ selector_specified = 1;
+ break;
+ case '?':
+ case 'h':
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Usage: %s [-s selector]\n", argv[0]),
+ 1);
+ } // switch
+ } // while getopt
+
+ // Create a server address.
+ ACE_ATM_Addr addr;
+ if (selector_specified)
+ addr.set_selector(selector);
+
+ // Create a server, reuse the addr.
+ ACE_TLI_Acceptor peer_acceptor;
+
+ // Not sure why but reuse_addr set to true/1 causes problems for
+ // FORE/XTI/ATM - this is now handled in ACE_TLI_Acceptor::open()
+ if (peer_acceptor.open (addr,
+ 1,
+ O_RDWR,
+ 0,
+ 5,
+ ACE_XTI_ATM_DEVICE) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%p\n",
+ "open"),
+ -1);
+
+ ACE_TLI_Stream new_stream;
+
+ ACE_DEBUG ((LM_DEBUG,
+ "starting server at address %s\n",
+ addr.addr_to_string ()));
+
+
+ // Performs the iterative server activities
+
+ for (;;)
+ {
+ char buf[BUFSIZ];
+
+ // Create a new ACE_TLI_Stream endpoint (note automatic restart
+ // if errno == EINTR).
+ if (peer_acceptor.accept (new_stream,
+ &addr,
+ &timeout) == -1)
+ {
+ ACE_ERROR ((LM_ERROR,
+ "%p\n",
+ "accept"));
+ continue;
+ }
+
+ ACE_DEBUG ((LM_DEBUG,
+ "client %s connected\n",
+ addr.addr_to_string ()));
+
+ // Read data from client (terminate on error).
+
+ for (int r_bytes;
+ (r_bytes = new_stream.recv (buf, sizeof buf, 0)) > 0; )
+ if (ACE_OS::write (ACE_STDOUT,
+ buf,
+ r_bytes) != r_bytes)
+ ACE_ERROR ((LM_ERROR,
+ "%p\n",
+ "ACE::send_n"));
+
+ // Close new endpoint (listening endpoint stays open).
+ if (new_stream.close () == -1)
+ ACE_ERROR ((LM_ERROR,
+ "%p\n",
+ "close"));
+
+ }
+ /* NOTREACHED */
+ return 0;
+}
+#else
+int ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "your platform isn't configured to support XTI/ATM\n"),
+ 1);
+}
+#endif /* ACE_HAS_TLI */
diff --git a/ACE/examples/IPC_SAP/TLI_SAP/CPP-client.cpp b/ACE/examples/IPC_SAP/TLI_SAP/CPP-client.cpp
new file mode 100644
index 00000000000..550356bba2e
--- /dev/null
+++ b/ACE/examples/IPC_SAP/TLI_SAP/CPP-client.cpp
@@ -0,0 +1,94 @@
+// $Id$
+
+#include "ace/TLI_Connector.h"
+#include "ace/INET_Addr.h"
+#include "ace/Log_Msg.h"
+#include "ace/OS_NS_stdlib.h"
+#include "ace/OS_NS_unistd.h"
+#include "ace/Time_Value.h"
+
+ACE_RCSID(TLI_SAP, CPP_client, "$Id$")
+
+#if defined (ACE_HAS_TLI)
+
+/* ACE_TLI Client */
+
+int ACE_TMAIN (int argc, ACE_TCHAR *argv[])
+{
+ const ACE_TCHAR *host = argc > 1 ? argv[1] : ACE_DEFAULT_SERVER_HOST;
+ u_short r_port = argc > 2 ? ACE_OS::atoi (argv[2]) : ACE_DEFAULT_SERVER_PORT;
+ int timeout = argc > 3 ? ACE_OS::atoi (argv[3]) : ACE_DEFAULT_TIMEOUT;
+ u_short l_port = argc > 4 ? ACE_OS::atoi (argv[4]) : ACE_DEFAULT_LOCAL_PORT;
+
+ char buf[BUFSIZ];
+
+ ACE_TLI_Stream cli_stream;
+
+ ACE_INET_Addr remote_addr (r_port, host);
+ ACE_INET_Addr local_addr (l_port);
+
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("starting non-blocking connect\n")));
+
+ // Initiate timed, non-blocking connection with server.
+ ACE_TLI_Connector con;
+
+ if (con.connect (cli_stream,
+ remote_addr,
+ (ACE_Time_Value *) &ACE_Time_Value::zero,
+ local_addr,
+ 1) == -1)
+ {
+ if (errno != EWOULDBLOCK)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("connection failed")),
+ 1);
+
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("starting timed connect\n")));
+
+ // Check if non-blocking connection is in progress, and wait up
+ // to timeout seconds for it to complete.
+ ACE_Time_Value tv (timeout);
+
+ if (con.complete (cli_stream,
+ &remote_addr,
+ &tv) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("connection failed")),
+ 1);
+ else
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("connected to %s\n"),
+ remote_addr.get_host_name ()));
+ }
+
+ // Send data to server (correctly handles "incomplete writes").
+
+ for (int r_bytes;
+ (r_bytes = ACE_OS::read (ACE_STDIN, buf, sizeof buf)) > 0;
+ )
+ if (cli_stream.send_n (buf,
+ r_bytes,
+ 0) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("send_n")),
+ 1);
+
+ // Explicitly close the connection.
+ if (cli_stream.close () == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("close")),
+ -1);
+ return 0;
+}
+#else
+int ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("your platform isn't configured to support TLI\n")),
+ 1);
+}
+#endif /* ACE_HAS_TLI */
diff --git a/ACE/examples/IPC_SAP/TLI_SAP/CPP-server.cpp b/ACE/examples/IPC_SAP/TLI_SAP/CPP-server.cpp
new file mode 100644
index 00000000000..4ed8c0bf643
--- /dev/null
+++ b/ACE/examples/IPC_SAP/TLI_SAP/CPP-server.cpp
@@ -0,0 +1,89 @@
+// $Id$
+
+#include "ace/TLI_Acceptor.h"
+#include "ace/Log_Msg.h"
+#include "ace/OS_NS_stdlib.h"
+#include "ace/OS_NS_unistd.h"
+
+ACE_RCSID(TLI_SAP, CPP_server, "$Id$")
+
+#if defined (ACE_HAS_TLI)
+// ACE_TLI Server
+
+int
+main (int argc, char *argv[])
+{
+ u_short port = argc > 1 ? ACE_OS::atoi (argv[1]) : ACE_DEFAULT_SERVER_PORT;
+ ACE_Time_Value timeout (argc > 2 ? ACE_OS::atoi (argv[2]) : ACE_DEFAULT_TIMEOUT);
+
+ // Create a server address.
+ ACE_INET_Addr addr (port);
+
+ // Create a server, reuse the addr.
+ ACE_TLI_Acceptor peer_acceptor;
+
+ // Not sure why but reuse_addr set to true/1 causes problems for
+ // FORE/XTI/ATM - this is now handled in ACE_TLI_Acceptor::open()
+ if (peer_acceptor.open (addr, 1) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%p\n",
+ "open"),
+ -1);
+
+ ACE_TLI_Stream new_stream;
+
+ ACE_DEBUG ((LM_DEBUG,
+ "starting server at host %s\n",
+ addr.get_host_name ()));
+
+ // Performs the iterative server activities
+
+ for (;;)
+ {
+ char buf[BUFSIZ];
+
+ // Create a new ACE_TLI_Stream endpoint (note automatic restart
+ // if errno == EINTR).
+ if (peer_acceptor.accept (new_stream,
+ &addr,
+ &timeout) == -1)
+ {
+ ACE_ERROR ((LM_ERROR,
+ "%p\n",
+ "accept"));
+ continue;
+ }
+
+ ACE_DEBUG ((LM_DEBUG,
+ "client %s connected\n",
+ addr.get_host_name ()));
+
+ // Read data from client (terminate on error).
+
+ for (int r_bytes;
+ (r_bytes = new_stream.recv (buf, sizeof buf)) > 0; )
+ if (ACE_OS::write (ACE_STDOUT,
+ buf,
+ r_bytes) != r_bytes)
+ ACE_ERROR ((LM_ERROR,
+ "%p\n",
+ "ACE::send_n"));
+
+ // Close new endpoint (listening endpoint stays open).
+ if (new_stream.close () == -1)
+ ACE_ERROR ((LM_ERROR,
+ "%p\n",
+ "close"));
+
+ }
+ /* NOTREACHED */
+ return 0;
+}
+#else
+int ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "your platform isn't configured to support TLI\n"),
+ 1);
+}
+#endif /* ACE_HAS_TLI */
diff --git a/ACE/examples/IPC_SAP/TLI_SAP/Makefile.am b/ACE/examples/IPC_SAP/TLI_SAP/Makefile.am
new file mode 100644
index 00000000000..80b48222d22
--- /dev/null
+++ b/ACE/examples/IPC_SAP/TLI_SAP/Makefile.am
@@ -0,0 +1,124 @@
+## Process this file with automake to create Makefile.in
+##
+## $Id$
+##
+## This file was generated by MPC. Any changes made directly to
+## this file will be lost the next time it is generated.
+##
+## MPC Command:
+## /acebuilds/ACE_wrappers-repository/bin/mwc.pl -include /acebuilds/MPC/config -include /acebuilds/MPC/templates -feature_file /acebuilds/ACE_wrappers-repository/local.features -noreldefs -type automake -exclude build,Kokyu
+
+ACE_BUILDDIR = $(top_builddir)
+ACE_ROOT = $(top_srcdir)
+
+## Makefile.TLI_SAP_ATM_Client.am
+noinst_PROGRAMS = ATM-client
+
+ATM_client_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+ATM_client_SOURCES = \
+ CPP-ATM-client.cpp
+
+ATM_client_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Makefile.TLI_SAP_ATM_Server.am
+noinst_PROGRAMS += ATM-server
+
+ATM_server_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+ATM_server_SOURCES = \
+ CPP-ATM-server.cpp
+
+ATM_server_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Makefile.TLI_SAP_CPP_Client.am
+noinst_PROGRAMS += CPP-client
+
+CPP_client_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+CPP_client_SOURCES = \
+ CPP-client.cpp
+
+CPP_client_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Makefile.TLI_SAP_CPP_Server.am
+noinst_PROGRAMS += CPP-server
+
+CPP_server_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+CPP_server_SOURCES = \
+ CPP-server.cpp
+
+CPP_server_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Makefile.TLI_SAP_Db_Client.am
+noinst_PROGRAMS += db-client
+
+db_client_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+db_client_SOURCES = \
+ db-client.cpp
+
+db_client_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Makefile.TLI_SAP_Db_Server.am
+noinst_PROGRAMS += db-server
+
+db_server_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+db_server_SOURCES = \
+ db-server.cpp
+
+db_server_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Makefile.TLI_SAP_Ftp_Client.am
+noinst_PROGRAMS += ftp-client
+
+ftp_client_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+ftp_client_SOURCES = \
+ ftp-client.cpp
+
+ftp_client_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Makefile.TLI_SAP_Ftp_Server.am
+noinst_PROGRAMS += ftp-server
+
+ftp_server_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+ftp_server_SOURCES = \
+ ftp-server.cpp
+
+ftp_server_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Clean up template repositories, etc.
+clean-local:
+ -rm -f *~ *.bak *.rpo *.sym lib*.*_pure_* core core.*
+ -rm -f gcctemp.c gcctemp so_locations *.ics
+ -rm -rf cxx_repository ptrepository ti_files
+ -rm -rf templateregistry ir.out
+ -rm -rf ptrepository SunWS_cache Templates.DB
diff --git a/ACE/examples/IPC_SAP/TLI_SAP/TLI_SAP.mpc b/ACE/examples/IPC_SAP/TLI_SAP/TLI_SAP.mpc
new file mode 100644
index 00000000000..0fe9b1aa17b
--- /dev/null
+++ b/ACE/examples/IPC_SAP/TLI_SAP/TLI_SAP.mpc
@@ -0,0 +1,58 @@
+// -*- MPC -*-
+// $Id$
+
+project(*ATM_client) : aceexe {
+ exename = ATM-client
+ Source_Files {
+ CPP-ATM-client.cpp
+ }
+}
+
+project(*ATM_server) : aceexe {
+ exename = ATM-server
+ Source_Files {
+ CPP-ATM-server.cpp
+ }
+}
+
+project(*CPP_client) : aceexe {
+ exename = CPP-client
+ Source_Files {
+ CPP-client.cpp
+ }
+}
+
+project(*CPP_server) : aceexe {
+ exename = CPP-server
+ Source_Files {
+ CPP-server.cpp
+ }
+}
+
+project(*db_client) : aceexe {
+ exename = db-client
+ Source_Files {
+ db-client.cpp
+ }
+}
+
+project(*db_server) : aceexe {
+ exename = db-server
+ Source_Files {
+ db-server.cpp
+ }
+}
+
+project(*ftp_client) : aceexe {
+ exename = ftp-client
+ Source_Files {
+ ftp-client.cpp
+ }
+}
+
+project(*ftp_server) : aceexe {
+ exename = ftp-server
+ Source_Files {
+ ftp-server.cpp
+ }
+}
diff --git a/ACE/examples/IPC_SAP/TLI_SAP/db-client.cpp b/ACE/examples/IPC_SAP/TLI_SAP/db-client.cpp
new file mode 100644
index 00000000000..6136d0ae4c5
--- /dev/null
+++ b/ACE/examples/IPC_SAP/TLI_SAP/db-client.cpp
@@ -0,0 +1,60 @@
+// $Id$
+
+#include "ace/TLI_Connector.h"
+#include "ace/Log_Msg.h"
+#include "ace/OS_NS_stdio.h"
+#include "ace/OS_NS_stdlib.h"
+#include "ace/OS_NS_string.h"
+
+ACE_RCSID(TLI_SAP, db_client, "$Id$")
+
+#if defined (ACE_HAS_TLI)
+const int MAXLINE = 255;
+
+int ACE_TMAIN (int argc, ACE_TCHAR *argv[])
+{
+ if (argc < 2)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("Usage: %s employee_id [server-host port-number]\n"),
+ argv[0]),
+ -1);
+
+ const ACE_TCHAR *emp_num = argv[1];
+ const ACE_TCHAR *host_name = argc < 3 ? ACE_DEFAULT_SERVER_HOST : argv[2];
+ unsigned short port = argc < 4 ? ACE_DEFAULT_SERVER_PORT : ACE_OS::atoi (argv[3]);
+ int n;
+ char buf[MAXLINE];
+
+ ACE_TLI_Stream client;
+ ACE_TLI_Connector con;
+
+ if (con.connect (client, ACE_INET_Addr (port, host_name)) == -1)
+ ACE_OS::t_error ((char *) host_name), ACE_OS::exit (1);
+
+ ACE_OS::strcpy (buf, ACE_TEXT_ALWAYS_CHAR (emp_num));
+ n = ACE_OS::strlen (buf);
+
+ if (client.send_n (buf, n) != n)
+ ACE_OS::t_error ("client.send error");
+
+ if (client.recv (buf, MAXLINE) == -1 && t_errno != TLOOK && client.look () != T_DISCONNECT)
+ ACE_OS::t_error ("client.recv error");
+
+ if (ACE_OS::strcmp (buf, "ERROR") == 0)
+ ACE_OS::printf ("Employee ID %s not in database\n", emp_num);
+ else
+ ACE_OS::printf ("Employee name requested is: %s\n", buf);
+
+ if (client.close () == -1)
+ ACE_OS::t_error ("cli_close"), ACE_OS::exit (1);
+
+ return 0;
+}
+#else
+int ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "your platform isn't configured to support TLI\n"),
+ 1);
+}
+#endif /* ACE_HAS_TLI */
diff --git a/ACE/examples/IPC_SAP/TLI_SAP/db-server.cpp b/ACE/examples/IPC_SAP/TLI_SAP/db-server.cpp
new file mode 100644
index 00000000000..145c4a13ad0
--- /dev/null
+++ b/ACE/examples/IPC_SAP/TLI_SAP/db-server.cpp
@@ -0,0 +1,121 @@
+// $Id$
+
+// Simple multi-threaded database server example.
+
+#include "ace/OS_NS_stdio.h"
+#include "ace/TLI_Acceptor.h"
+#include "ace/Thread_Manager.h"
+
+ACE_RCSID(TLI_SAP, db_server, "$Id$")
+
+#if defined (ACE_HAS_THREADS) && defined (ACE_HAS_TLI)
+
+// Global thread manager.
+ACE_Thread_Manager thr_mgr;
+
+void *
+lookup_name (ACE_HANDLE handle)
+{
+ enum
+ {
+ MAXLINE = 255,
+ EMPNAMELEN = 512
+ };
+
+ static struct
+ {
+ int emp_id;
+ const char *emp_name;
+ } employee_db[] =
+ {
+ {123, "John Wayne Bobbit"},
+ {124, "Woody Allen"},
+ {125, "O. J. Simpson"},
+ {126, "Bill Clinton"},
+ {127, "Rush Limbaugh"},
+ {128, "Michael Jackson"},
+ {129, "Kenneth Starr"},
+ {130, "Paula Jones"},
+ {131, "Monica Lewinsky"},
+ {132, "Marv Albert"},
+ {0, ""}
+ };
+
+ int flags;
+ int employee_id;
+ int index;
+ int found;
+ ACE_TLI_Stream stream;
+ char recvline[MAXLINE];
+ char sendline[MAXLINE];
+
+ ACE_DEBUG ((LM_DEBUG,
+ "stream handle = %d, thread id = %t\n",
+ handle));
+ stream.set_handle (handle);
+
+ ssize_t n = stream.recv (recvline, MAXLINE, &flags);
+
+ if (n == -1)
+ ACE_OS::t_error ("stream.recv error");
+
+ employee_id = ACE_OS::atoi (recvline);
+ found = 0;
+
+ for (index = 0; found == 0 && employee_db[index].emp_id; index++)
+ if (employee_id == employee_db[index].emp_id)
+ {
+ found = 1;
+ n = ACE_OS::sprintf (sendline,
+ "%s", employee_db[index].emp_name);
+ }
+
+ if (found == 0)
+ n = ACE_OS::sprintf (sendline, "%s", "ERROR");
+
+ if (stream.send (sendline, n + 1, 0) == -1)
+ ACE_OS::t_error ("stream.send error");
+
+ if (stream.sndrel () == -1)
+ ACE_OS::t_error ("stream.send error");
+
+ if (stream.close () == -1)
+ ACE_OS::t_error ("stream.close error");
+
+ return 0;
+}
+
+int
+main (int argc, char *argv[])
+{
+ u_short port = argc > 1 ? ACE_OS::atoi (argv[1]) : ACE_DEFAULT_SERVER_PORT;
+ ACE_INET_Addr l_addr (port);
+ ACE_TLI_Acceptor server (l_addr, 1); // Create server, reuse addr if in use.
+ ACE_TLI_Stream new_stream;
+
+ // Wait for a connection from a client. This is an example of a
+ // concurrent server.
+
+ for (;;)
+ {
+ if (server.accept (new_stream) == -1)
+ ACE_OS::t_error ("server.accept error");
+
+ if (thr_mgr.spawn (ACE_THR_FUNC (lookup_name),
+ (void *) new_stream.get_handle (),
+ THR_DETACHED) == -1)
+ ACE_DEBUG ((LM_ERROR,
+ "server: can't create worker thread %d\n"));
+ }
+
+ ACE_NOTREACHED (return 0);
+}
+#else
+#include <stdio.h>
+int ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "platform isn't configured to support TLI\n"),
+ 1);
+}
+#endif /* ACE_HAS_THREADS */
diff --git a/ACE/examples/IPC_SAP/TLI_SAP/ftp-client.cpp b/ACE/examples/IPC_SAP/TLI_SAP/ftp-client.cpp
new file mode 100644
index 00000000000..c783e0aba55
--- /dev/null
+++ b/ACE/examples/IPC_SAP/TLI_SAP/ftp-client.cpp
@@ -0,0 +1,54 @@
+// $Id$
+
+#include "ace/TLI_Connector.h"
+#include "ace/Log_Msg.h"
+#include "ace/OS_NS_fcntl.h"
+#include "ace/OS_NS_stdio.h"
+#include "ace/OS_NS_stdlib.h"
+#include "ace/OS_NS_unistd.h"
+
+ACE_RCSID(TLI_SAP, ftp_client, "$Id$")
+
+#if defined (ACE_HAS_TLI)
+
+int ACE_TMAIN (int argc, ACE_TCHAR *argv[])
+{
+ if (argc < 2)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("Usage: %s filename ")
+ ACE_TEXT ("[server-host port-number]\n"),
+ argv[0]),
+ 1);
+
+ const ACE_TCHAR *filename = argv[1];
+ const ACE_TCHAR *host_name = argc < 3 ? ACE_DEFAULT_SERVER_HOST : argv[2];
+ u_short port = argc < 4 ? ACE_DEFAULT_SERVER_PORT : ACE_OS::atoi (argv[3]);
+
+ ACE_TLI_Stream client;
+ ACE_TLI_Connector con;
+ int fd;
+ char buf[BUFSIZ];
+
+ if (con.connect (client, ACE_INET_Addr (port, host_name)) == -1)
+ ACE_OS::t_error ((char *) host_name), ACE_OS::exit (1);
+
+ if ((fd = ACE_OS::open (filename, O_RDONLY)) == -1)
+ ACE_OS::perror (filename), ACE_OS::exit (1);
+
+ for (int n; (n = ACE_OS::read (fd, buf, sizeof buf)) > 0; )
+ if (client.send_n (buf, n) != n)
+ ACE_OS::t_error ("client.send error");
+
+ if (client.close () == -1)
+ ACE_OS::t_error ("cli_close"), ACE_OS::exit (1);
+
+ return 0;
+}
+#else
+int ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("your platform isn't configured to support TLI\n")),
+ 1);
+}
+#endif /* ACE_HAS_TLI */
diff --git a/ACE/examples/IPC_SAP/TLI_SAP/ftp-server.cpp b/ACE/examples/IPC_SAP/TLI_SAP/ftp-server.cpp
new file mode 100644
index 00000000000..23596a84dd4
--- /dev/null
+++ b/ACE/examples/IPC_SAP/TLI_SAP/ftp-server.cpp
@@ -0,0 +1,83 @@
+// $Id$
+
+// Simple file transfer example
+
+#include "ace/OS_NS_stdio.h"
+#include "ace/Thread_Manager.h"
+#include "ace/TLI_Acceptor.h"
+
+ACE_RCSID(TLI_SAP, ftp_server, "$Id$")
+
+#if defined (ACE_HAS_THREADS) && defined (ACE_HAS_TLI)
+
+ACE_Thread_Manager thr_mgr;
+
+void *
+read_file (void *fd)
+{
+ ACE_TLI_Stream stream;
+ char buf[BUFSIZ];
+ int flags = 0;
+ ssize_t n;
+
+ // Cast the arg to a long, first, because a pointer is the same size
+ // as a long on all current ACE platforms.
+ stream.set_handle ((int) (long) fd);
+
+ ACE_DEBUG((LM_DEBUG, "start (tid = %t, fd = %d)\n",
+ stream.get_handle ()));
+
+ while ((n = stream.recv (buf, sizeof buf, &flags)) > 0)
+ continue;
+
+ ACE_UNUSED_ARG (n);
+
+ ACE_DEBUG ((LM_DEBUG,"finish (tid = %t, fd = %d)\n",
+ stream.get_handle ()));
+
+ if (stream.close () == -1)
+ ACE_OS::t_error ("stream.close error");
+
+ return 0;
+}
+
+int
+main (int argc, char *argv[])
+{
+ u_short port = argc > 1 ? ACE_OS::atoi (argv[1]) : ACE_DEFAULT_SERVER_PORT;
+ ACE_TLI_Acceptor server;
+ ACE_TLI_Stream new_stream;
+
+ // Open the server and reuse the address if in use...
+ if (server.open (ACE_INET_Addr (port), 1) == -1)
+ ACE_OS::t_error ("server.open"), ACE_OS::exit (1);
+
+ // Wait for a connection from a client. This is an example of a
+ // concurrent server.
+
+ for (int count = 1; ; count++)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ "thread %t, blocking for accept #%d\n",
+ count));
+
+ if (server.accept (new_stream) == -1)
+ ACE_OS::t_error ("server.accept error");
+
+ else if (thr_mgr.spawn (ACE_THR_FUNC (read_file),
+ (void *) new_stream.get_handle (),
+ THR_DETACHED | THR_BOUND) == -1)
+ ACE_OS::perror ("can't create worker thread\n");
+ }
+
+ ACE_NOTREACHED (return 0);
+}
+#else
+#include <stdio.h>
+int ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "your platform isn't configured to support TLI\n"),
+ 1);
+}
+#endif /* ACE_HAS_THREADS */
diff --git a/ACE/examples/IPC_SAP/UPIPE_SAP/.cvsignore b/ACE/examples/IPC_SAP/UPIPE_SAP/.cvsignore
new file mode 100644
index 00000000000..66a3e2ba941
--- /dev/null
+++ b/ACE/examples/IPC_SAP/UPIPE_SAP/.cvsignore
@@ -0,0 +1,6 @@
+ex1
+ex1
+ex2
+ex2
+ex3
+ex3
diff --git a/ACE/examples/IPC_SAP/UPIPE_SAP/Makefile.am b/ACE/examples/IPC_SAP/UPIPE_SAP/Makefile.am
new file mode 100644
index 00000000000..60054e3c7c0
--- /dev/null
+++ b/ACE/examples/IPC_SAP/UPIPE_SAP/Makefile.am
@@ -0,0 +1,73 @@
+## Process this file with automake to create Makefile.in
+##
+## $Id$
+##
+## This file was generated by MPC. Any changes made directly to
+## this file will be lost the next time it is generated.
+##
+## MPC Command:
+## /acebuilds/ACE_wrappers-repository/bin/mwc.pl -include /acebuilds/MPC/config -include /acebuilds/MPC/templates -feature_file /acebuilds/ACE_wrappers-repository/local.features -noreldefs -type automake -exclude build,Kokyu
+
+ACE_BUILDDIR = $(top_builddir)
+ACE_ROOT = $(top_srcdir)
+
+noinst_PROGRAMS =
+
+## Makefile.UPIPE_SAP_Ex1.am
+
+if !BUILD_ACE_FOR_TAO
+noinst_PROGRAMS += ex1
+
+ex1_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+ex1_SOURCES = \
+ ex1.cpp
+
+ex1_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+endif !BUILD_ACE_FOR_TAO
+
+## Makefile.UPIPE_SAP_Ex2.am
+
+if !BUILD_ACE_FOR_TAO
+noinst_PROGRAMS += ex2
+
+ex2_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+ex2_SOURCES = \
+ ex2.cpp
+
+ex2_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+endif !BUILD_ACE_FOR_TAO
+
+## Makefile.UPIPE_SAP_Ex3.am
+
+if !BUILD_ACE_FOR_TAO
+noinst_PROGRAMS += ex3
+
+ex3_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+ex3_SOURCES = \
+ ex3.cpp
+
+ex3_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+endif !BUILD_ACE_FOR_TAO
+
+## Clean up template repositories, etc.
+clean-local:
+ -rm -f *~ *.bak *.rpo *.sym lib*.*_pure_* core core.*
+ -rm -f gcctemp.c gcctemp so_locations *.ics
+ -rm -rf cxx_repository ptrepository ti_files
+ -rm -rf templateregistry ir.out
+ -rm -rf ptrepository SunWS_cache Templates.DB
diff --git a/ACE/examples/IPC_SAP/UPIPE_SAP/UPIPE_SAP.mpc b/ACE/examples/IPC_SAP/UPIPE_SAP/UPIPE_SAP.mpc
new file mode 100644
index 00000000000..d34d8671735
--- /dev/null
+++ b/ACE/examples/IPC_SAP/UPIPE_SAP/UPIPE_SAP.mpc
@@ -0,0 +1,26 @@
+// -*- MPC -*-
+// $Id$
+
+project(*ex1) : aceexe {
+ avoids += ace_for_tao
+ exename = ex1
+ Source_Files {
+ ex1.cpp
+ }
+}
+
+project(*ex2) : aceexe {
+ avoids += ace_for_tao
+ exename = ex2
+ Source_Files {
+ ex2.cpp
+ }
+}
+
+project(*ex3) : aceexe {
+ avoids += ace_for_tao
+ exename = ex3
+ Source_Files {
+ ex3.cpp
+ }
+}
diff --git a/ACE/examples/IPC_SAP/UPIPE_SAP/ex1.cpp b/ACE/examples/IPC_SAP/UPIPE_SAP/ex1.cpp
new file mode 100644
index 00000000000..39ad86d5819
--- /dev/null
+++ b/ACE/examples/IPC_SAP/UPIPE_SAP/ex1.cpp
@@ -0,0 +1,183 @@
+// $Id$
+
+// ============================================================================
+//
+// = LIBRARY
+// examples
+//
+// = FILENAME
+// ex1.cpp
+//
+// = DESCRIPTION
+// Example for using <ACE_UPIPE_SAP> and <ACE_Thread> for
+// intra-process communication.
+//
+// = AUTHOR
+// Gerhard Lenzer and Douglas C. Schmidt
+//
+// ============================================================================
+
+#include "ace/OS_main.h"
+#include "ace/OS_NS_string.h"
+#include "ace/Stream.h"
+#include "ace/UPIPE_Acceptor.h"
+#include "ace/UPIPE_Connector.h"
+
+ACE_RCSID(UPIPE_SAP, ex1, "$Id$")
+
+#if defined (ACE_HAS_THREADS)
+
+// Global pattern
+static ACE_UPIPE_Addr addr (ACE_TEXT("pattern"));
+
+// peer1 thread entry point.
+
+static void *
+peer1 (void *)
+{
+ ACE_UPIPE_Stream c_stream;
+
+ ACE_DEBUG ((LM_DEBUG,
+ "(%t) peer1 starting connect\n"));
+ ACE_UPIPE_Connector con;
+
+ if (con.connect (c_stream, addr) == -1)
+ ACE_ERROR ((LM_ERROR,
+ "(%t) peer1 ACE_UPIPE_Connector failed\n"));
+
+ ACE_Message_Block *mb;
+ ACE_NEW_RETURN (mb,
+ ACE_Message_Block (20),
+ 0);
+
+ mb->copy ("hello", 6);
+
+ if (c_stream.send (mb) == -1)
+ ACE_ERROR ((LM_ERROR,
+ "(%t) error peer1 send\n"));
+
+ if (c_stream.recv (mb) == -1)
+ ACE_ERROR ((LM_ERROR,
+ "(%t) error peer1 recv\n"));
+
+ ACE_ERROR ((LM_ERROR,
+ "(%t) peer1 ack is \"%s\"\n",
+ mb->rd_ptr ()));
+
+ // Free up the memory block.
+ mb->release ();
+
+ // Now try the send()/recv() interface.
+ char mytext[] = "This string is sent by peer1 as buffer";
+
+ ACE_ERROR ((LM_ERROR,
+ "(%t) peer1 sending text\n"));
+ if (c_stream.send (mytext, sizeof mytext) == -1)
+ ACE_ERROR ((LM_ERROR,
+ "(%t) buffer send from peer1 failed\n"));
+
+ char conbuf[30]; // Buffer to receive response.
+
+ int i = 0;
+
+ for (char c = ' '; c != '!'; i++)
+ {
+ if (c_stream.recv (&c, 1) == -1)
+ ACE_ERROR ((LM_ERROR,
+ "(%t) buffer recv from peer1 failed\n"));
+ else
+ conbuf[i] = c;
+ }
+
+ conbuf[i] = '\0';
+ ACE_DEBUG ((LM_DEBUG,
+ "(%t) peer1 received buffer with \"%s\"\n",
+ conbuf));
+ c_stream.close ();
+ return 0;
+}
+
+static void *
+peer2 (void *)
+{
+ ACE_UPIPE_Acceptor acc (addr);
+ ACE_UPIPE_Stream s_stream;
+
+ // Spawn a peer1 thread.
+ if (ACE_Thread_Manager::instance ()->spawn (ACE_THR_FUNC (peer1),
+ (void *) 0,
+ THR_NEW_LWP | THR_DETACHED) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%p\n",
+ "spawn"),
+ 0);
+
+ ACE_DEBUG ((LM_DEBUG,
+ "(%t) peer2 starting accept\n"));
+
+ if (acc.accept (s_stream) == -1)
+ ACE_ERROR ((LM_ERROR,
+ "(%t) ACE_UPIPE_Acceptor.accept failed\n"));
+
+ ACE_Message_Block *mb = 0;
+
+ if (s_stream.recv (mb) == -1)
+ ACE_ERROR ((LM_ERROR,
+ "(%t) peer2 recv failed\n"));
+
+ ACE_DEBUG ((LM_DEBUG, "(%t) peer2 recv is \"%s\"\n",
+ mb->rd_ptr ()));
+
+ mb->wr_ptr (mb->rd_ptr ());
+ mb->copy ("thanks", 7);
+
+ if (s_stream.send (mb) == -1)
+ ACE_ERROR ((LM_ERROR,
+ "(%t) peer2 send failed\n"));
+
+ char s_buf[42];
+ ACE_DEBUG ((LM_DEBUG,
+ "(%t) peer2 sleeping on recv\n"));
+
+ if (s_stream.recv (s_buf, sizeof s_buf) == -1)
+ ACE_ERROR ((LM_ERROR,
+ "(%t) peer2 recv failed\n"));
+ else
+ ACE_DEBUG ((LM_DEBUG,
+ "(%t) peer2 received buffer with \"%s\"\n",
+ s_buf));
+
+ ACE_OS::strcpy (s_buf,
+ "this is the peer2 response!");
+
+ if (s_stream.send (s_buf, 30) == -1)
+ ACE_ERROR ((LM_ERROR,
+ "(%t) peer2 send failed\n"));
+ s_stream.close ();
+ return 0;
+}
+
+int
+ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ // Spawn a peer2 thread.
+ if (ACE_Thread_Manager::instance ()->spawn (ACE_THR_FUNC (peer2),
+ (void *) 0,
+ THR_NEW_LWP | THR_DETACHED) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%p\n",
+ "spawn"),
+ 1);
+ // Wait for peer2 and peer1 threads to exit.
+ ACE_Thread_Manager::instance ()->wait ();
+ return 0;
+}
+#else
+int
+ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "threads not supported on this platform\n"),
+ -1);
+}
+#endif /* ACE_HAS_THREADS */
diff --git a/ACE/examples/IPC_SAP/UPIPE_SAP/ex2.cpp b/ACE/examples/IPC_SAP/UPIPE_SAP/ex2.cpp
new file mode 100644
index 00000000000..e19a83460ce
--- /dev/null
+++ b/ACE/examples/IPC_SAP/UPIPE_SAP/ex2.cpp
@@ -0,0 +1,179 @@
+// $Id$
+
+// ============================================================================
+//
+// = LIBRARY
+// examples
+//
+// = FILENAME
+// ex2.cpp
+//
+// = DESCRIPTION
+// Example for using <ACE_UPIPE_SAP> and <ACE_Thread> for
+// intra-process communication.
+//
+// = AUTHOR
+// Gerhard Lenzer and Douglas C. Schmidt
+//
+// ============================================================================
+
+#include "ace/OS_main.h"
+#include "ace/UPIPE_Connector.h"
+#include "ace/UPIPE_Acceptor.h"
+#include "ace/Auto_Ptr.h"
+#include "ace/OS_NS_time.h"
+
+ACE_RCSID(UPIPE_SAP, ex2, "$Id$")
+
+#if defined (ACE_HAS_THREADS)
+
+// Data for testsuite.
+static int size = 0;
+static int iterations = 0;
+
+static void *
+supplier (void *)
+{
+ ACE_UPIPE_Stream s_stream;
+
+ ACE_UPIPE_Addr c_addr (ACE_TEXT("pattern"));
+
+ ACE_Auto_Basic_Array_Ptr<char> mybuf (new char[size]);
+
+ for (int i = 0; i < size; i++)
+ mybuf[i] = 'a';
+
+ ACE_DEBUG ((LM_DEBUG,
+ "(%t) supplier starting connect thread\n"));
+
+ ACE_UPIPE_Connector con;
+
+ if (con.connect (s_stream, c_addr) == -1)
+ ACE_ERROR ((LM_ERROR,
+ "(%t) %p\n",
+ "ACE_UPIPE_Acceptor.connect failed"));
+
+ // Test asynchronicity (the "acausal principle" ;-)).
+ s_stream.enable (ACE_SIGIO);
+
+ ACE_Message_Block *mb_p;
+
+ for (int j = 0; j < iterations; j++)
+ {
+ ACE_NEW_RETURN (mb_p,
+ ACE_Message_Block (size,
+ ACE_Message_Block::MB_DATA,
+ (ACE_Message_Block *) 0,
+ mybuf.get ()),
+ 0);
+ if (s_stream.send (mb_p) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "(%t) %p\n",
+ "send failed"),
+ 0);
+ }
+
+ ACE_NEW_RETURN (mb_p,
+ ACE_Message_Block ((size_t) 0),
+ 0);
+
+ // Insert a 0-sized message block to signal the other side to shut
+ // down.
+ if (s_stream.send (mb_p) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "(%t) %p\n",
+ "send failed"),
+ 0);
+ s_stream.close ();
+ return 0;
+}
+
+static void *
+consumer (void *)
+{
+ ACE_UPIPE_Stream c_stream;
+
+ // Set the high water mark to size to achieve optimum performance.
+
+ int wm = size * iterations;
+
+ if (c_stream.control (ACE_IO_Cntl_Msg::SET_HWM,
+ &wm) == -1)
+ ACE_DEBUG ((LM_DEBUG,
+ "set HWM failed\n"));
+
+ ACE_UPIPE_Addr serv_addr (ACE_TEXT("pattern"));
+
+ // accept will wait up to 4 seconds
+ ACE_UPIPE_Acceptor acc (serv_addr);
+
+ ACE_DEBUG ((LM_DEBUG,
+ "(%t) consumer spawning the supplier thread\n"));
+
+ // Spawn the supplier thread.
+ if (ACE_Thread_Manager::instance ()->spawn (ACE_THR_FUNC (supplier),
+ (void *) 0,
+ THR_NEW_LWP | THR_DETACHED) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%p\n",
+ "spawn"),
+ 0);
+
+ ACE_DEBUG ((LM_DEBUG,
+ "(%t) consumer starting accept\n"));
+
+ if (acc.accept (c_stream) == -1)
+ ACE_ERROR ((LM_ERROR,
+ "(%t) %p\n",
+ "ACE_UPIPE_Acceptor.accept failed"));
+
+ // Time measurement.
+ time_t currsec;
+ ACE_OS::time (&currsec);
+ time_t start = (time_t) currsec;
+
+ int received_messages = 0;
+
+ for (ACE_Message_Block *mb = 0;
+ c_stream.recv (mb) != -1 && mb->size () != 0;
+ mb->release ())
+ received_messages++;
+
+ ACE_OS::time (&currsec);
+ time_t secs = (time_t) currsec - start;
+
+ ACE_DEBUG ((LM_DEBUG,
+ "(%t) Transferred %d blocks of size %d\n"
+ "The program ran %d seconds\n",
+ received_messages, size, secs));
+ c_stream.close ();
+ return 0;
+}
+
+int
+ACE_TMAIN (int argc, ACE_TCHAR *argv[])
+{
+ size = argc > 1 ? ACE_OS::atoi (argv[1]) : 32;
+ iterations = argc > 2 ? ACE_OS::atoi (argv[2]) : 16;
+
+ // Spawn the two threads.
+ if (ACE_Thread_Manager::instance ()->spawn (ACE_THR_FUNC (consumer),
+ (void *) 0,
+ THR_NEW_LWP | THR_DETACHED) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%p\n",
+ "spawn"),
+ 1);
+ // Wait for producer and consumer threads to exit.
+ ACE_Thread_Manager::instance ()->wait ();
+ return 0;
+}
+#else
+int
+ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "threads not supported on this platform\n"),
+ 0);
+}
+#endif /* ACE_HAS_THREADS */
diff --git a/ACE/examples/IPC_SAP/UPIPE_SAP/ex3.cpp b/ACE/examples/IPC_SAP/UPIPE_SAP/ex3.cpp
new file mode 100644
index 00000000000..57ff4f34d9e
--- /dev/null
+++ b/ACE/examples/IPC_SAP/UPIPE_SAP/ex3.cpp
@@ -0,0 +1,159 @@
+// $Id$
+
+// ============================================================================
+//
+// = LIBRARY
+// examples
+//
+// = FILENAME
+// ex3.cpp
+//
+// = DESCRIPTION
+// Example for using <ACE_UPIPE_SAP> and <ACE_Thread> for intra-process
+// communication. This example uses char buffers as input/output
+// interface to the <ACE_UPIPE_Stream>.
+//
+// = AUTHOR
+// Gerhard Lenzer and Prashant Jain.
+//
+// ============================================================================
+
+#include "ace/OS_main.h"
+#include "ace/UPIPE_Connector.h"
+#include "ace/UPIPE_Acceptor.h"
+#include "ace/Auto_Ptr.h"
+#include "ace/OS_NS_time.h"
+
+ACE_RCSID(UPIPE_SAP, ex3, "$Id$")
+
+#if defined (ACE_HAS_THREADS)
+
+// Data for testsuite.
+static int size = 0;
+static int iterations = 0;
+
+static void *
+supplier (void *)
+{
+ ACE_UPIPE_Stream s_stream;
+ ACE_UPIPE_Addr c_addr (ACE_TEXT("pattern"));
+
+ ACE_UPIPE_Connector con;
+
+ ACE_DEBUG ((LM_DEBUG,
+ "(%t) supplier starting connect thread\n"));
+
+ if (con.connect (s_stream, c_addr) == -1)
+ ACE_ERROR ((LM_ERROR,
+ "(%t) %p\n",
+ "ACE_UPIPE_Acceptor.connect failed"));
+
+ ACE_Auto_Basic_Array_Ptr<char> mybuf (new char[size]);
+
+ for (int i = 0; i < size; i++)
+ mybuf[i] = 'a';
+
+ for (int j = 0; j < iterations; j++)
+ if (s_stream.send (mybuf.get (), size) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "(%t) %p\n", "send failed"),
+ 0);
+
+ // Insert a 0-sized message block to signal the other side to shut
+ // down.
+ if (s_stream.send (new ACE_Message_Block ((size_t) 0)) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "(%t) %p\n", "error put"),
+ 0);
+ s_stream.close ();
+ return 0;
+}
+
+static void *
+consumer (void *)
+{
+ ACE_UPIPE_Stream c_stream;
+ ACE_UPIPE_Addr serv_addr (ACE_TEXT("pattern"));
+
+ // Accept will wait up to 4 seconds
+ ACE_UPIPE_Acceptor acc (serv_addr);
+
+ ACE_DEBUG ((LM_DEBUG,
+ "(%t) consumer spawning the supplier thread\n"));
+
+ // Spawn the supplier thread.
+ if (ACE_Thread_Manager::instance ()->spawn (ACE_THR_FUNC (supplier),
+ (void *) 0,
+ THR_NEW_LWP | THR_DETACHED) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%p\n",
+ "spawn"),
+ 0);
+ ACE_DEBUG ((LM_DEBUG,
+ "(%t) consumer starting accept\n"));
+
+ if (acc.accept (c_stream) == -1)
+ ACE_ERROR ((LM_ERROR, "(%t) %p\n",
+ "ACE_UPIPE_Acceptor.accept failed"));
+
+ // Ensure deletion upon exit.
+ ACE_Auto_Basic_Array_Ptr<char> mybuf (new char[size]);
+ time_t currsec;
+
+ ACE_OS::time (&currsec);
+
+ time_t start = (time_t) currsec;
+ int result = 0;
+ int blocks = 0;
+
+ for (;; blocks++)
+ {
+ result = c_stream.recv (mybuf.get (), size);
+ if (result <= 0)
+ break;
+ }
+
+ if (result == -1)
+ ACE_ERROR ((LM_ERROR,
+ "(%t) %p\n", "recv failed"));
+
+ ACE_OS::time (&currsec);
+ time_t secs = (time_t) currsec - start;
+
+ ACE_DEBUG ((LM_DEBUG,
+ "(%t) Transferred %d blocks of size %d\n"
+ "The program ran %d seconds\n",
+ blocks,
+ size,
+ secs));
+ c_stream.close ();
+ return 0;
+}
+
+int
+ACE_TMAIN (int argc, ACE_TCHAR *argv[])
+{
+ size = argc > 1 ? ACE_OS::atoi (argv[1]) : 32;
+ iterations = argc > 2 ? ACE_OS::atoi (argv[2]) : 16;
+
+ // Spawn the thread.
+ if (ACE_Thread_Manager::instance ()->spawn (ACE_THR_FUNC (consumer),
+ (void *) 0,
+ THR_NEW_LWP | THR_DETACHED) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%p\n",
+ "spawn"),
+ 1);
+ // Wait for producer and consumer threads to exit.
+ ACE_Thread_Manager::instance ()->wait ();
+ return 0;
+}
+#else
+int
+ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "threads not supported on this platform\n"),
+ 0);
+}
+#endif /* ACE_HAS_THREADS */
diff --git a/ACE/examples/Log_Msg/.cvsignore b/ACE/examples/Log_Msg/.cvsignore
new file mode 100644
index 00000000000..c4e57879139
--- /dev/null
+++ b/ACE/examples/Log_Msg/.cvsignore
@@ -0,0 +1,6 @@
+test_callback
+test_callback
+test_log_msg
+test_log_msg
+test_ostream
+test_ostream
diff --git a/ACE/examples/Log_Msg/Log_Msg.mpc b/ACE/examples/Log_Msg/Log_Msg.mpc
new file mode 100644
index 00000000000..0c7b0f67563
--- /dev/null
+++ b/ACE/examples/Log_Msg/Log_Msg.mpc
@@ -0,0 +1,23 @@
+// -*- MPC -*-
+// $Id$
+
+project(*test_log_msg) : aceexe {
+ exename = test_log_msg
+ Source_Files {
+ test_log_msg.cpp
+ }
+}
+
+project(*test_ostream) : aceexe {
+ exename = test_ostream
+ Source_Files {
+ test_ostream.cpp
+ }
+}
+
+project(*test_callback) : aceexe {
+ exename = test_callback
+ Source_Files {
+ test_callback.cpp
+ }
+}
diff --git a/ACE/examples/Log_Msg/Log_Msg_MFC/Log_Msg_MFC.cpp b/ACE/examples/Log_Msg/Log_Msg_MFC/Log_Msg_MFC.cpp
new file mode 100644
index 00000000000..5aa9c95f0d4
--- /dev/null
+++ b/ACE/examples/Log_Msg/Log_Msg_MFC/Log_Msg_MFC.cpp
@@ -0,0 +1,90 @@
+// Log_Msg_MFC.cpp : Defines the class behaviors for the application.
+// $Id$
+
+#include "ace/Log_Msg.h"
+#include "Log_Msg_MFC.h"
+
+#if defined (ACE_WIN32)
+
+#include "stdafx.h"
+#include "Log_Msg_MFCDlg.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+#include <ace/ACE.h>
+
+/////////////////////////////////////////////////////////////////////////////
+// CLog_Msg_MFCApp
+
+BEGIN_MESSAGE_MAP(CLog_Msg_MFCApp, CWinApp)
+ //{{AFX_MSG_MAP(CLog_Msg_MFCApp)
+ // NOTE - the ClassWizard will add and remove mapping macros here.
+ // DO NOT EDIT what you see in these blocks of generated code!
+ //}}AFX_MSG
+ ON_COMMAND(ID_HELP, CWinApp::OnHelp)
+END_MESSAGE_MAP()
+
+/////////////////////////////////////////////////////////////////////////////
+// CLog_Msg_MFCApp construction
+
+CLog_Msg_MFCApp::CLog_Msg_MFCApp()
+{
+ // TODO: add construction code here,
+ // Place all significant initialization in InitInstance
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// The one and only CLog_Msg_MFCApp object
+
+CLog_Msg_MFCApp theApp;
+
+/////////////////////////////////////////////////////////////////////////////
+// CLog_Msg_MFCApp initialization
+
+BOOL CLog_Msg_MFCApp::InitInstance()
+{
+ // Standard initialization
+ // If you are not using these features and wish to reduce the size
+ // of your final executable, you should remove from the following
+ // the specific initialization routines you do not need.
+
+ // Need to call ACE::init() before calling any functions in ACE.
+ // If we were writing a console based application, the ACE macros which
+ // re-define main() would automatically call this. However, since
+ // we are running inside an MFC application, we need to explicitly call this.
+ ACE::init();
+
+ // Call to set the ACE Log_Msg class here.
+ // From now on, whenever we use ACE_DEBUG macros, the output
+ // will be sent to the log() method of our MFC_Log class.
+ ACE_Log_Msg::instance()->msg_callback( &m_mfc_logger );
+ ACE_Log_Msg::instance()->set_flags( ACE_Log_Msg::MSG_CALLBACK );
+
+ CLog_Msg_MFCDlg dlg;
+ m_pMainWnd = &dlg;
+ int nResponse = dlg.DoModal();
+ if (nResponse == IDOK)
+ {
+ // TODO: Place code here to handle when the dialog is
+ // dismissed with OK
+ }
+ else if (nResponse == IDCANCEL)
+ {
+ // TODO: Place code here to handle when the dialog is
+ // dismissed with Cancel
+ }
+
+ // Since we called ACE::init(), we need to call ACE:fini(), otherwise
+ // the debugger will complain about memory leaks.
+ ACE::fini();
+
+ // Since the dialog has been closed, return FALSE so that we exit the
+ // application, rather than start the application's message pump.
+ return FALSE;
+}
+
+#endif /* ACE_WIN32 */
diff --git a/ACE/examples/Log_Msg/Log_Msg_MFC/Log_Msg_MFC.h b/ACE/examples/Log_Msg/Log_Msg_MFC/Log_Msg_MFC.h
new file mode 100644
index 00000000000..66940811ba1
--- /dev/null
+++ b/ACE/examples/Log_Msg/Log_Msg_MFC/Log_Msg_MFC.h
@@ -0,0 +1,62 @@
+// Log_Msg_MFC.h : main header file for the LOG_MSG_MFC application
+// $Id$
+
+#if !defined(AFX_LOG_MSG_MFC_H__03FA2C60_71EA_44F9_AC4C_2F19168B4755__INCLUDED_)
+#define AFX_LOG_MSG_MFC_H__03FA2C60_71EA_44F9_AC4C_2F19168B4755__INCLUDED_
+
+#include "ace/config-all.h"
+
+#if defined (ACE_WIN32)
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+
+#ifndef __AFXWIN_H__
+ #error include 'stdafx.h' before including this file for PCH
+#endif
+
+#include "resource.h" // main symbols
+
+// Add some includes here for our Logger
+#include "MFC_Log.h"
+
+/////////////////////////////////////////////////////////////////////////////
+// CLog_Msg_MFCApp:
+// See Log_Msg_MFC.cpp for the implementation of this class
+//
+
+class CLog_Msg_MFCApp : public CWinApp
+{
+public:
+ CLog_Msg_MFCApp();
+
+// Overrides
+ // ClassWizard generated virtual function overrides
+ //{{AFX_VIRTUAL(CLog_Msg_MFCApp)
+ public:
+ virtual BOOL InitInstance();
+ //}}AFX_VIRTUAL
+
+// Implementation
+
+ //{{AFX_MSG(CLog_Msg_MFCApp)
+ // NOTE - the ClassWizard will add and remove member functions here.
+ // DO NOT EDIT what you see in these blocks of generated code !
+ //}}AFX_MSG
+ DECLARE_MESSAGE_MAP()
+
+ // MFC Log class for ACE_Log_Msg. To be used by ACE_DEBUG
+ MFC_Log m_mfc_logger;
+
+};
+
+
+/////////////////////////////////////////////////////////////////////////////
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
+
+#endif /* ACE_WIN32 */
+
+#endif // !defined(AFX_LOG_MSG_MFC_H__03FA2C60_71EA_44F9_AC4C_2F19168B4755__INCLUDED_)
diff --git a/ACE/examples/Log_Msg/Log_Msg_MFC/Log_Msg_MFC.mpc b/ACE/examples/Log_Msg/Log_Msg_MFC/Log_Msg_MFC.mpc
new file mode 100644
index 00000000000..fea7e91ec9f
--- /dev/null
+++ b/ACE/examples/Log_Msg/Log_Msg_MFC/Log_Msg_MFC.mpc
@@ -0,0 +1,12 @@
+// -*- MPC -*-
+// $Id$
+
+project : aceexe, ace_mfc {
+ exename = Log_Msg_MFC
+ Source_Files {
+ Log_Msg_MFC.cpp
+ Log_Msg_MFCDlg.cpp
+ MFC_Log.cpp
+ StdAfx.cpp
+ }
+}
diff --git a/ACE/examples/Log_Msg/Log_Msg_MFC/Log_Msg_MFC.rc b/ACE/examples/Log_Msg/Log_Msg_MFC/Log_Msg_MFC.rc
new file mode 100644
index 00000000000..5f2f04dce74
--- /dev/null
+++ b/ACE/examples/Log_Msg/Log_Msg_MFC/Log_Msg_MFC.rc
@@ -0,0 +1,207 @@
+//Microsoft Developer Studio generated resource script.
+//
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include "afxres.h"
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// English (U.S.) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
+#ifdef _WIN32
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+#pragma code_page(1252)
+#endif //_WIN32
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE DISCARDABLE
+BEGIN
+ "resource.h\0"
+END
+
+2 TEXTINCLUDE DISCARDABLE
+BEGIN
+ "#include ""afxres.h""\r\n"
+ "\0"
+END
+
+3 TEXTINCLUDE DISCARDABLE
+BEGIN
+ "#define _AFX_NO_SPLITTER_RESOURCES\r\n"
+ "#define _AFX_NO_OLE_RESOURCES\r\n"
+ "#define _AFX_NO_TRACKER_RESOURCES\r\n"
+ "#define _AFX_NO_PROPERTY_RESOURCES\r\n"
+ "\r\n"
+ "#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)\r\n"
+ "#ifdef _WIN32\r\n"
+ "LANGUAGE 9, 1\r\n"
+ "#pragma code_page(1252)\r\n"
+ "#endif //_WIN32\r\n"
+ "#include ""res\\Log_Msg_MFC.rc2"" // non-Microsoft Visual C++ edited resources\r\n"
+ "#include ""afxres.rc"" // Standard components\r\n"
+ "#endif\r\n"
+ "\0"
+END
+
+#endif // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Icon
+//
+
+// Icon with lowest ID value placed first to ensure application icon
+// remains consistent on all systems.
+IDR_MAINFRAME ICON DISCARDABLE "res\\Log_Msg_MFC.ico"
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Dialog
+//
+
+IDD_ABOUTBOX DIALOG DISCARDABLE 0, 0, 235, 55
+STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "About Log_Msg_MFC"
+FONT 8, "MS Sans Serif"
+BEGIN
+ ICON IDR_MAINFRAME,IDC_STATIC,11,17,20,20
+ LTEXT "Log_Msg_MFC Version 1.0",IDC_STATIC,40,10,119,8,
+ SS_NOPREFIX
+ LTEXT "Copyright (C) 2002",IDC_STATIC,40,25,119,8
+ DEFPUSHBUTTON "OK",IDOK,178,7,50,14,WS_GROUP
+END
+
+IDD_LOG_MSG_MFC_DIALOG DIALOGEX 0, 0, 320, 200
+STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
+EXSTYLE WS_EX_APPWINDOW
+CAPTION "Log_Msg_MFC"
+FONT 8, "MS Sans Serif"
+BEGIN
+ DEFPUSHBUTTON "OK",IDOK,241,170,50,14
+ PUSHBUTTON "DebugMe",IDC_BUTTON1,92,96,50,14
+ LTEXT "Run this program inside the Visual Studio debugger. Press the DebugMe button and see the ACE_DEBUG messages appear in the Visual Studio debug console.",
+ IDC_STATIC,83,28,116,56
+END
+
+
+#ifndef _MAC
+/////////////////////////////////////////////////////////////////////////////
+//
+// Version
+//
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION 1,0,0,1
+ PRODUCTVERSION 1,0,0,1
+ FILEFLAGSMASK 0x3fL
+#ifdef _DEBUG
+ FILEFLAGS 0x1L
+#else
+ FILEFLAGS 0x0L
+#endif
+ FILEOS 0x4L
+ FILETYPE 0x1L
+ FILESUBTYPE 0x0L
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "040904B0"
+ BEGIN
+ VALUE "CompanyName", "\0"
+ VALUE "FileDescription", "Log_Msg_MFC MFC Application\0"
+ VALUE "FileVersion", "1, 0, 0, 1\0"
+ VALUE "InternalName", "Log_Msg_MFC\0"
+ VALUE "LegalCopyright", "Copyright (C) 2002\0"
+ VALUE "LegalTrademarks", "\0"
+ VALUE "OriginalFilename", "Log_Msg_MFC.EXE\0"
+ VALUE "ProductName", "Log_Msg_MFC Application\0"
+ VALUE "ProductVersion", "1, 0, 0, 1\0"
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x409, 1200
+ END
+END
+
+#endif // !_MAC
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// DESIGNINFO
+//
+
+#ifdef APSTUDIO_INVOKED
+GUIDELINES DESIGNINFO DISCARDABLE
+BEGIN
+ IDD_ABOUTBOX, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 228
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 48
+ END
+
+ IDD_LOG_MSG_MFC_DIALOG, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 313
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 193
+ END
+END
+#endif // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// String Table
+//
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ IDS_ABOUTBOX "&About Log_Msg_MFC..."
+END
+
+#endif // English (U.S.) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+#define _AFX_NO_SPLITTER_RESOURCES
+#define _AFX_NO_OLE_RESOURCES
+#define _AFX_NO_TRACKER_RESOURCES
+#define _AFX_NO_PROPERTY_RESOURCES
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
+#ifdef _WIN32
+LANGUAGE 9, 1
+#pragma code_page(1252)
+#endif //_WIN32
+#include "res\Log_Msg_MFC.rc2" // non-Microsoft Visual C++ edited resources
+#include "afxres.rc" // Standard components
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
+
diff --git a/ACE/examples/Log_Msg/Log_Msg_MFC/Log_Msg_MFCDlg.cpp b/ACE/examples/Log_Msg/Log_Msg_MFC/Log_Msg_MFCDlg.cpp
new file mode 100644
index 00000000000..ec014f9d9eb
--- /dev/null
+++ b/ACE/examples/Log_Msg/Log_Msg_MFC/Log_Msg_MFCDlg.cpp
@@ -0,0 +1,185 @@
+// Log_Msg_MFCDlg.cpp : implementation file
+// $Id$
+
+#include "Log_Msg_MFC.h"
+
+#if defined (ACE_WIN32)
+
+#include "ace/Log_Msg.h"
+#include "stdafx.h"
+#include "Log_Msg_MFCDlg.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+// CAboutDlg dialog used for App About
+
+class CAboutDlg : public CDialog
+{
+public:
+ CAboutDlg();
+
+// Dialog Data
+ //{{AFX_DATA(CAboutDlg)
+ enum { IDD = IDD_ABOUTBOX };
+ //}}AFX_DATA
+
+ // ClassWizard generated virtual function overrides
+ //{{AFX_VIRTUAL(CAboutDlg)
+ protected:
+ virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
+ //}}AFX_VIRTUAL
+
+// Implementation
+protected:
+ //{{AFX_MSG(CAboutDlg)
+ //}}AFX_MSG
+ DECLARE_MESSAGE_MAP()
+};
+
+CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
+{
+ //{{AFX_DATA_INIT(CAboutDlg)
+ //}}AFX_DATA_INIT
+}
+
+void CAboutDlg::DoDataExchange(CDataExchange* pDX)
+{
+ CDialog::DoDataExchange(pDX);
+ //{{AFX_DATA_MAP(CAboutDlg)
+ //}}AFX_DATA_MAP
+}
+
+BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
+ //{{AFX_MSG_MAP(CAboutDlg)
+ // No message handlers
+ //}}AFX_MSG_MAP
+END_MESSAGE_MAP()
+
+/////////////////////////////////////////////////////////////////////////////
+// CLog_Msg_MFCDlg dialog
+
+CLog_Msg_MFCDlg::CLog_Msg_MFCDlg(CWnd* pParent /*=NULL*/)
+ : CDialog(CLog_Msg_MFCDlg::IDD, pParent)
+{
+ //{{AFX_DATA_INIT(CLog_Msg_MFCDlg)
+ // NOTE: the ClassWizard will add member initialization here
+ //}}AFX_DATA_INIT
+ // Note that LoadIcon does not require a subsequent DestroyIcon in Win32
+ m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
+}
+
+void CLog_Msg_MFCDlg::DoDataExchange(CDataExchange* pDX)
+{
+ CDialog::DoDataExchange(pDX);
+ //{{AFX_DATA_MAP(CLog_Msg_MFCDlg)
+ // NOTE: the ClassWizard will add DDX and DDV calls here
+ //}}AFX_DATA_MAP
+}
+
+BEGIN_MESSAGE_MAP(CLog_Msg_MFCDlg, CDialog)
+ //{{AFX_MSG_MAP(CLog_Msg_MFCDlg)
+ ON_WM_SYSCOMMAND()
+ ON_WM_PAINT()
+ ON_WM_QUERYDRAGICON()
+ ON_BN_CLICKED(IDC_BUTTON1, OnDebugButtonClicked)
+ ON_WM_CLOSE()
+ //}}AFX_MSG_MAP
+END_MESSAGE_MAP()
+
+/////////////////////////////////////////////////////////////////////////////
+// CLog_Msg_MFCDlg message handlers
+
+BOOL CLog_Msg_MFCDlg::OnInitDialog()
+{
+ CDialog::OnInitDialog();
+
+
+ // Add "About..." menu item to system menu.
+
+ // IDM_ABOUTBOX must be in the system command range.
+ ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
+ ASSERT(IDM_ABOUTBOX < 0xF000);
+
+#if !defined (_WIN32_WCE)
+ CMenu* pSysMenu = GetSystemMenu(FALSE);
+ if (pSysMenu != NULL)
+ {
+ CString strAboutMenu;
+ strAboutMenu.LoadString(IDS_ABOUTBOX);
+ if (!strAboutMenu.IsEmpty())
+ {
+ pSysMenu->AppendMenu(MF_SEPARATOR);
+ pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
+ }
+ }
+#endif /* !_WIN32_WCE */
+
+ // Set the icon for this dialog. The framework does this automatically
+ // when the application's main window is not a dialog
+ SetIcon(m_hIcon, TRUE); // Set big icon
+ SetIcon(m_hIcon, FALSE); // Set small icon
+
+ // TODO: Add extra initialization here
+
+ return TRUE; // return TRUE unless you set the focus to a control
+}
+
+void CLog_Msg_MFCDlg::OnSysCommand(UINT nID, LPARAM lParam)
+{
+ if ((nID & 0xFFF0) == IDM_ABOUTBOX)
+ {
+ CAboutDlg dlgAbout;
+ dlgAbout.DoModal();
+ }
+ else
+ {
+ CDialog::OnSysCommand(nID, lParam);
+ }
+}
+
+// If you add a minimize button to your dialog, you will need the code below
+// to draw the icon. For MFC applications using the document/view model,
+// this is automatically done for you by the framework.
+
+void CLog_Msg_MFCDlg::OnPaint()
+{
+ if (IsIconic())
+ {
+ CPaintDC dc(this); // device context for painting
+
+ // Center icon in client rectangle
+ int cxIcon = GetSystemMetrics(SM_CXICON);
+ int cyIcon = GetSystemMetrics(SM_CYICON);
+ CRect rect;
+ GetClientRect(&rect);
+ int x = (rect.Width() - cxIcon + 1) / 2;
+ int y = (rect.Height() - cyIcon + 1) / 2;
+
+ // Draw the icon
+ dc.DrawIcon(x, y, m_hIcon);
+ }
+ else
+ {
+ CDialog::OnPaint();
+ }
+}
+
+// The system calls this to obtain the cursor to display while the user drags
+// the minimized window.
+HCURSOR CLog_Msg_MFCDlg::OnQueryDragIcon()
+{
+ return (HCURSOR) m_hIcon;
+}
+
+void CLog_Msg_MFCDlg::OnDebugButtonClicked()
+{
+ ACE_DEBUG(( LM_DEBUG, "Debug message sent!\n" ));
+
+}
+
+#endif /* ACE_WIN32 */
diff --git a/ACE/examples/Log_Msg/Log_Msg_MFC/Log_Msg_MFCDlg.h b/ACE/examples/Log_Msg/Log_Msg_MFC/Log_Msg_MFCDlg.h
new file mode 100644
index 00000000000..0a26de3e5e7
--- /dev/null
+++ b/ACE/examples/Log_Msg/Log_Msg_MFC/Log_Msg_MFCDlg.h
@@ -0,0 +1,59 @@
+// Log_Msg_MFCDlg.h : header file
+// $Id$
+
+#if !defined(AFX_LOG_MSG_MFCDLG_H__5BB9CACE_CBCE_40DD_B57F_ED05B79DB033__INCLUDED_)
+#define AFX_LOG_MSG_MFCDLG_H__5BB9CACE_CBCE_40DD_B57F_ED05B79DB033__INCLUDED_
+
+#include "ace/config-all.h"
+
+#if defined (ACE_WIN32)
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+
+#include "Resource.h"
+
+/////////////////////////////////////////////////////////////////////////////
+// CLog_Msg_MFCDlg dialog
+
+class CLog_Msg_MFCDlg : public CDialog
+{
+// Construction
+public:
+ CLog_Msg_MFCDlg(CWnd* pParent = NULL); // standard constructor
+
+// Dialog Data
+ //{{AFX_DATA(CLog_Msg_MFCDlg)
+ enum { IDD = IDD_LOG_MSG_MFC_DIALOG };
+ // NOTE: the ClassWizard will add data members here
+ //}}AFX_DATA
+
+ // ClassWizard generated virtual function overrides
+ //{{AFX_VIRTUAL(CLog_Msg_MFCDlg)
+ protected:
+ virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
+ //}}AFX_VIRTUAL
+
+// Implementation
+protected:
+ HICON m_hIcon;
+
+ // Generated message map functions
+ //{{AFX_MSG(CLog_Msg_MFCDlg)
+ virtual BOOL OnInitDialog();
+ afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
+ afx_msg void OnPaint();
+ afx_msg HCURSOR OnQueryDragIcon();
+ afx_msg void OnDebugButtonClicked();
+ //}}AFX_MSG
+ DECLARE_MESSAGE_MAP()
+
+};
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
+
+#endif /* ACE_WIN32 */
+
+#endif // !defined(AFX_LOG_MSG_MFCDLG_H__5BB9CACE_CBCE_40DD_B57F_ED05B79DB033__INCLUDED_)
diff --git a/ACE/examples/Log_Msg/Log_Msg_MFC/MFC_Log.cpp b/ACE/examples/Log_Msg/Log_Msg_MFC/MFC_Log.cpp
new file mode 100644
index 00000000000..18899d5611c
--- /dev/null
+++ b/ACE/examples/Log_Msg/Log_Msg_MFC/MFC_Log.cpp
@@ -0,0 +1,45 @@
+// $Id$
+// MFC_Log.cpp: implementation of the MFC_Log class.
+//
+//////////////////////////////////////////////////////////////////////
+
+#include "ace/OS_NS_stdio.h"
+#include "MFC_Log.h"
+
+#if defined (ACE_WIN32)
+# include "stdafx.h"
+#endif /* ACE_WIN32 */
+
+#include "ace/Log_Record.h"
+#include "ace/Time_Value.h"
+
+//////////////////////////////////////////////////////////////////////
+// Construction/Destruction
+//////////////////////////////////////////////////////////////////////
+
+MFC_Log::MFC_Log ()
+{
+
+}
+
+void
+MFC_Log::log (ACE_Log_Record& log_record)
+{
+ unsigned long priority = log_record.type();
+ ACE_TCHAR Message[512];
+
+ ACE_OS::sprintf (Message,
+ ACE_TEXT ("%d.%03ld %s"),
+ log_record.time_stamp().sec(),
+ log_record.time_stamp().usec()/ 1000,
+ log_record.msg_data());
+
+#if defined (ACE_WIN32)
+ ACE_TEXT_OutputDebugString(Message);
+#endif /* ACE_WIN32 */
+}
+
+MFC_Log::~MFC_Log ()
+{
+
+}
diff --git a/ACE/examples/Log_Msg/Log_Msg_MFC/MFC_Log.h b/ACE/examples/Log_Msg/Log_Msg_MFC/MFC_Log.h
new file mode 100644
index 00000000000..657b0e8a914
--- /dev/null
+++ b/ACE/examples/Log_Msg/Log_Msg_MFC/MFC_Log.h
@@ -0,0 +1,47 @@
+/* -*- C++ -*- */
+
+//=============================================================================
+/**
+ * @file MFC_Log.h
+ *
+ * $Id$
+ *
+ * @author Craig Rodrigues <crodrigu@bbn.com>
+ * @author Chris Hafey <chafey@stentor.com>
+ * @author Don Hinton <dhinton@ieee.org>
+ */
+//=============================================================================
+
+#ifndef MFC_LOG_H
+#define MFC_LOG_H
+
+#include "ace/Log_Msg_Callback.h"
+
+class ACE_Log_Record;
+
+/**
+ * @class MFC_Log
+ *
+ * @brief A callback class for ACE_Log_Msg which sends output to
+ * Microsoft debugger
+ *
+ * Register this class as a MSG_CALLBACK with the ACE_Log_Msg singleton and
+ * send debug output to the Microsoft debugger console window with
+ * ACE_DEBUG macros.
+ */
+class MFC_Log : public virtual ACE_Log_Msg_Callback
+{
+public:
+ /// Constructor
+ MFC_Log();
+
+ /// method called by ACE_Log_Msg to log an event
+ void log(ACE_Log_Record& log_record);
+
+ /// destructor
+ virtual ~MFC_Log();
+
+};
+
+#endif /* MFC_LOG_H */
+
diff --git a/ACE/examples/Log_Msg/Log_Msg_MFC/README b/ACE/examples/Log_Msg/Log_Msg_MFC/README
new file mode 100644
index 00000000000..d64001aff87
--- /dev/null
+++ b/ACE/examples/Log_Msg/Log_Msg_MFC/README
@@ -0,0 +1,40 @@
+ MFC Logging Example documentation
+ =================================
+ by Craig Rodrigues <crodrigu@bbn.com>
+ 2002/08/02
+
+The example in this directory is a Microsoft Foundation Class (MFC)
+example which illustrates how to write an ACE_Log_Msg_Callback which
+can send debug output to the Microsoft debugger console.
+
+This is very useful when debugging an MFC GUI-based application which
+uses ACE.
+
+NOTES
+=====
+ - Make sure that $ACE_ROOT/ace/acemfcd.lib is built before building this
+ example. Follow the instructions in $ACE_ROOT/ACE-INSTALL.html for building
+ ACE with Visual C++. Do a Batch Build of ACE, and make sure that you build
+ the target "ACE DLL - Win32 MFC Debug".
+
+ - We must call ACE::init() and ACE::fini() in the right places
+ otherwise we will get strange crashes and memory leaks
+ when invoking ACE_Log_Msg::instance().
+ A good place to invoke these methods is in the method which overrides
+ CWinApp::InitInstance().
+ In this example, we invoke these methods in CLog_Msg_MFCApp::InitInstance().
+
+ - We must set the ACE_Log_Msg singleton to use our callback with:
+ ACE_Log_Msg::instance()->msg_callback( &m_mfc_logger );
+ ACE_Log_Msg::instance()->set_flags( ACE_Log_Msg::MSG_CALLBACK );
+
+ This is also done in CLog_Msg_MFCApp::InitInstance().
+
+
+THANKS
+======
+Thanks to the following people who provided assistance on the ACE
+mailing list:
+Chris Hafey <chafey@stentor.com>
+Don Hinton <dhinton@ieee.org>
+
diff --git a/ACE/examples/Log_Msg/Log_Msg_MFC/Resource.h b/ACE/examples/Log_Msg/Log_Msg_MFC/Resource.h
new file mode 100644
index 00000000000..d1aa3df6ce1
--- /dev/null
+++ b/ACE/examples/Log_Msg/Log_Msg_MFC/Resource.h
@@ -0,0 +1,21 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Developer Studio generated include file.
+// Used by Log_Msg_MFC.rc
+// $Id$
+#define IDM_ABOUTBOX 0x0010
+#define IDD_ABOUTBOX 100
+#define IDS_ABOUTBOX 101
+#define IDD_LOG_MSG_MFC_DIALOG 102
+#define IDR_MAINFRAME 128
+#define IDC_BUTTON1 1000
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 129
+#define _APS_NEXT_COMMAND_VALUE 32771
+#define _APS_NEXT_CONTROL_VALUE 1001
+#define _APS_NEXT_SYMED_VALUE 101
+#endif
+#endif
diff --git a/ACE/examples/Log_Msg/Log_Msg_MFC/StdAfx.cpp b/ACE/examples/Log_Msg/Log_Msg_MFC/StdAfx.cpp
new file mode 100644
index 00000000000..7325df7a861
--- /dev/null
+++ b/ACE/examples/Log_Msg/Log_Msg_MFC/StdAfx.cpp
@@ -0,0 +1,9 @@
+// $Id$
+// stdafx.cpp : source file that includes just the standard includes
+// Log_Msg_MFC.pch will be the pre-compiled header
+// stdafx.obj will contain the pre-compiled type information
+
+#include "stdafx.h"
+
+
+
diff --git a/ACE/examples/Log_Msg/Log_Msg_MFC/StdAfx.h b/ACE/examples/Log_Msg/Log_Msg_MFC/StdAfx.h
new file mode 100644
index 00000000000..caf39678fcb
--- /dev/null
+++ b/ACE/examples/Log_Msg/Log_Msg_MFC/StdAfx.h
@@ -0,0 +1,28 @@
+// stdafx.h : include file for standard system include files,
+// or project specific include files that are used frequently, but
+// are changed infrequently
+// $Id$
+
+#if !defined(AFX_STDAFX_H__41816CD6_CE58_4714_8C74_1C67651B50ED__INCLUDED_)
+#define AFX_STDAFX_H__41816CD6_CE58_4714_8C74_1C67651B50ED__INCLUDED_
+
+#ifdef USING_PCH
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+
+#define VC_EXTRALEAN // Exclude rarely-used stuff from Windows headers
+
+#include <afxwin.h> // MFC core and standard components
+#include <afxext.h> // MFC extensions
+#include <afxdtctl.h> // MFC support for Internet Explorer 4 Common Controls
+#ifndef _AFX_NO_AFXCMN_SUPPORT
+#include <afxcmn.h> // MFC support for Windows Common Controls
+#endif // _AFX_NO_AFXCMN_SUPPORT
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
+
+#endif // USING_PCH
+#endif // !defined(AFX_STDAFX_H__41816CD6_CE58_4714_8C74_1C67651B50ED__INCLUDED_)
diff --git a/ACE/examples/Log_Msg/Log_Msg_MFC/res/Log_Msg_MFC.ico b/ACE/examples/Log_Msg/Log_Msg_MFC/res/Log_Msg_MFC.ico
new file mode 100644
index 00000000000..7eef0bcbe65
--- /dev/null
+++ b/ACE/examples/Log_Msg/Log_Msg_MFC/res/Log_Msg_MFC.ico
Binary files differ
diff --git a/ACE/examples/Log_Msg/Log_Msg_MFC/res/Log_Msg_MFC.rc2 b/ACE/examples/Log_Msg/Log_Msg_MFC/res/Log_Msg_MFC.rc2
new file mode 100644
index 00000000000..f8d03632acf
--- /dev/null
+++ b/ACE/examples/Log_Msg/Log_Msg_MFC/res/Log_Msg_MFC.rc2
@@ -0,0 +1,13 @@
+//
+// LOG_MSG_MFC.RC2 - resources Microsoft Visual C++ does not edit directly
+//
+
+#ifdef APSTUDIO_INVOKED
+ #error this file is not editable by Microsoft Visual C++
+#endif //APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+// Add manually edited resources here...
+
+/////////////////////////////////////////////////////////////////////////////
diff --git a/ACE/examples/Log_Msg/Makefile.am b/ACE/examples/Log_Msg/Makefile.am
new file mode 100644
index 00000000000..c5d038d332d
--- /dev/null
+++ b/ACE/examples/Log_Msg/Makefile.am
@@ -0,0 +1,59 @@
+## Process this file with automake to create Makefile.in
+##
+## $Id$
+##
+## This file was generated by MPC. Any changes made directly to
+## this file will be lost the next time it is generated.
+##
+## MPC Command:
+## /acebuilds/ACE_wrappers-repository/bin/mwc.pl -include /acebuilds/MPC/config -include /acebuilds/MPC/templates -feature_file /acebuilds/ACE_wrappers-repository/local.features -noreldefs -type automake -exclude build,Kokyu
+
+ACE_BUILDDIR = $(top_builddir)
+ACE_ROOT = $(top_srcdir)
+
+## Makefile.Log_Msg_Test_Callback.am
+noinst_PROGRAMS = test_callback
+
+test_callback_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+test_callback_SOURCES = \
+ test_callback.cpp
+
+test_callback_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Makefile.Log_Msg_Test_Log_Msg.am
+noinst_PROGRAMS += test_log_msg
+
+test_log_msg_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+test_log_msg_SOURCES = \
+ test_log_msg.cpp
+
+test_log_msg_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Makefile.Log_Msg_Test_Ostream.am
+noinst_PROGRAMS += test_ostream
+
+test_ostream_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+test_ostream_SOURCES = \
+ test_ostream.cpp
+
+test_ostream_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Clean up template repositories, etc.
+clean-local:
+ -rm -f *~ *.bak *.rpo *.sym lib*.*_pure_* core core.*
+ -rm -f gcctemp.c gcctemp so_locations *.ics
+ -rm -rf cxx_repository ptrepository ti_files
+ -rm -rf templateregistry ir.out
+ -rm -rf ptrepository SunWS_cache Templates.DB
diff --git a/ACE/examples/Log_Msg/README b/ACE/examples/Log_Msg/README
new file mode 100644
index 00000000000..047caf9ca77
--- /dev/null
+++ b/ACE/examples/Log_Msg/README
@@ -0,0 +1,65 @@
+This directory contains program(s) that demonstrate how to use ACE's
+Log_Msg class to record various information.
+
+ * test_callback.cpp: This program tests the Log_Msg
+ abstraction wrt writing to user defined callback objects.
+
+ * test_ostream.cpp: This program illustrates how the
+ ACE_Log_Msg abstraction can be used to write to
+ stderr and to a file. For even more sophisticated
+ use-cases of ACE_Log_Msg please see the
+ $ACE_ROOT/netsvcs/clients/Logger/ examples.
+
+ * test_log_msg.cpp: This program tests various feature of the
+ Log_Msg facility. It opens a log file and writes some
+ messages using different log priorities and output stream.
+
+ You can invoke the program with or without command
+ parameters. When invoked with any parameters like,
+
+ ./Log_Msg foobar
+
+ the log messages are direct to stdout (or, ostream in C++.)
+ In this case, the program simulates an error EWOULDBLOCK and
+ write an error log to stdout as,
+
+ would block
+ op_status and errnum work!
+
+ When invoked without any parameters, except does the same
+ test as above but logs to default log stream "stderr," the
+ program also demonstrates logging messages/errors with
+ different priority and changing the logging destination. A
+ sample output is,
+
+ would block
+ op_status and errnum work!
+ 3.141600, hello = 10000
+ 6.283200, world = 20000
+ 6.283200, world = 20000
+ 9.424800, world = 30000
+ 12.566400, world = 40000
+ 15.708000, world = 50000
+ HEXDUMP 48 bytes
+ 01 00 00 00 02 00 00 00 04 00 00 00 08 00 00 00 ................
+ 10 00 00 00 20 00 00 00 40 00 00 00 80 00 00 00 .... ...@.......
+ 00 01 00 00 00 02 00 00 00 04 00 00 00 08 00 00 ................
+ ./Log_Msg.EXE: (2710), badname: Function not implemented
+
+ In this test, there are two lines containing "world` =
+ 20000." That's because in the program, both stderr and
+ stdout are "turned on" for logging before writing this log
+ message. The line containing "world = 30000" is written to
+ stdout only. Rest of the lines are all to the stderr. You
+ can examine this behavior by redirecting stderr and stdout
+ to different files.
+
+ The HEXDUMP output shows how to take an arbitrary object and
+ hexdump its content for debugging. Finally, the program
+ shows an ordinary use case of logging error messages using
+ the ACE_ERROR macro.
+
+ If you look into the program, there is also a demonstration
+ showing how to disable certain priorities of error message
+ temporarily.
+
diff --git a/ACE/examples/Log_Msg/test_callback.cpp b/ACE/examples/Log_Msg/test_callback.cpp
new file mode 100644
index 00000000000..e263c9777eb
--- /dev/null
+++ b/ACE/examples/Log_Msg/test_callback.cpp
@@ -0,0 +1,166 @@
+// $Id$
+
+// ============================================================================
+//
+// = LIBRARY
+// examples/Log_Msg
+//
+// = FILENAME
+// test_callback.cpp
+//
+// = DESCRIPTION
+// This program tests the <ACE_Log_Msg> class wrt writing to user
+// defined callback objects. In particular, it tests to make sure
+// that nested callbacks don't deadlock.
+//
+// = AUTHOR
+// Irfan Pyarali <irfan@cs.wustl.edu>
+//
+// ============================================================================
+
+#include "ace/OS_main.h"
+#include "ace/Log_Msg.h"
+#include "ace/Log_Msg_Callback.h"
+#include "ace/Log_Record.h"
+#include "ace/OS_NS_stdio.h"
+
+ACE_RCSID(Log_Msg, test_callback, "$Id$")
+
+class Logger : public ACE_Log_Msg_Callback
+// Subclassing from ACE_Log_Msg_Callback means that an instance of
+// Logger can be a target of a callback.
+{
+public:
+ // Constructor sets whether we're testing "recursive" callback
+ // logging!
+ Logger (int be_recursive = 1);
+
+ virtual void log (ACE_Log_Record &log_record);
+ // Logging callback hook.
+
+ void verbose (int be_verbose);
+
+private:
+ int verbose_logging_;
+ // Flag for testing verbose logging.
+
+ int recursive_;
+ // Flag for testing recursive callback logging.
+};
+
+void
+Logger::verbose (int be_verbose)
+{
+ this->verbose_logging_ = be_verbose;
+}
+
+Logger::Logger (int be_recursive)
+ : recursive_ (be_recursive)
+{
+}
+
+void
+Logger::log (ACE_Log_Record &log_record)
+{
+ int use_log_msg = 0;
+
+ if (this->recursive_)
+ {
+ this->recursive_ = 0;
+ use_log_msg = 1;
+ }
+
+ if (!this->verbose_logging_)
+ {
+ if (use_log_msg)
+ ACE_DEBUG ((LM_DEBUG,
+ "Logger::log->%s",
+ log_record.msg_data ()));
+ else
+ ACE_OS::printf ("Recursive Logger callback = %s",
+ log_record.msg_data ());
+ }
+ else
+ {
+ ACE_TCHAR verbose_msg[ACE_Log_Record::MAXVERBOSELOGMSGLEN];
+ int result = log_record.format_msg (ACE_LOG_MSG->local_host (),
+ ACE_LOG_MSG->flags (),
+ verbose_msg);
+ if (result == 0)
+ {
+ if (use_log_msg)
+ ACE_DEBUG ((LM_DEBUG,
+ "Logger::log->%s",
+ verbose_msg));
+ else
+ ACE_OS::printf ("Recursive Logger callback = %s",
+ verbose_msg);
+ }
+ }
+
+ // Cleanup on the way out.
+ if (use_log_msg)
+ this->recursive_ = 1;
+}
+
+int
+ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ // This message should show up in stderr.
+ ACE_DEBUG ((LM_DEBUG,
+ "(%t) first message\n"));
+
+ ACE_LOG_MSG->clr_flags (ACE_Log_Msg::STDERR);
+
+ // This message should not show up anywhere since we disabled STDERR.
+ ACE_DEBUG ((LM_DEBUG,
+ "(%t) second message\n"));
+
+ ACE_LOG_MSG->set_flags (ACE_Log_Msg::MSG_CALLBACK);
+
+ // This message should not show up anywhere since no callback object
+ // has been specified.
+ ACE_DEBUG ((LM_DEBUG,
+ "(%t) third message\n"));
+
+ // Create a callback object and make it "verbose".
+ Logger logger;
+ logger.verbose (1);
+
+ // Set the callback object.
+ ACE_LOG_MSG->msg_callback (&logger);
+
+ // This message should show up via the Logger callback.
+ ACE_DEBUG ((LM_DEBUG,
+ "(%t) fourth message\n"));
+
+ ACE_LOG_MSG->set_flags (ACE_Log_Msg::VERBOSE_LITE);
+
+ // This message should show up via the Logger callback (somewhat
+ // verbosely).
+ ACE_DEBUG ((LM_DEBUG,
+ "(%t) fifth message\n"));
+
+ ACE_LOG_MSG->set_flags (ACE_Log_Msg::VERBOSE);
+
+ // This message should show up via the Logger callback (really
+ // verbosely).
+ ACE_DEBUG ((LM_DEBUG,
+ "(%t) sixth message\n"));
+
+ logger.verbose (0);
+
+ // This message should show up via the Logger callback (not
+ // verbosely).
+ ACE_DEBUG ((LM_DEBUG,
+ "(%t) seventh message\n"));
+
+ ACE_LOG_MSG->set_flags (ACE_Log_Msg::STDERR);
+
+ // This message should show up in stderr and the Logger callback.
+ // The one from the Logger callback will not be verbose, but the one
+ // from stderr should be verbose.
+ ACE_DEBUG ((LM_DEBUG,
+ "(%t) eighth message\n"));
+ return 0;
+}
diff --git a/ACE/examples/Log_Msg/test_log_msg.cpp b/ACE/examples/Log_Msg/test_log_msg.cpp
new file mode 100644
index 00000000000..a2d40770f56
--- /dev/null
+++ b/ACE/examples/Log_Msg/test_log_msg.cpp
@@ -0,0 +1,218 @@
+// $Id$
+
+// ============================================================================
+//
+// = LIBRARY
+// examples/Log_Msg
+//
+// = FILENAME
+// test_log_msg.cpp
+//
+// = DESCRIPTION
+// This program tests the ACE_Log_Msg abstraction and demontrates
+// several common use cases.
+//
+// = AUTHOR
+// Douglas Schmidt <schmidt@cs.wustl.edu>
+//
+// ============================================================================
+
+#include "ace/OS_main.h"
+
+// FUZZ: disable check_for_streams_include
+#include "ace/streams.h"
+
+#include "ace/Log_Msg.h"
+#include "ace/OS_NS_unistd.h"
+#include "ace/OS_NS_stdlib.h"
+
+ACE_RCSID(Log_Msg, test_log_msg, "$Id$")
+
+static void
+cleanup (void)
+{
+ ACE_DEBUG ((LM_INFO,
+ "leaving (%P)!\n"));
+}
+
+static void
+cause_error (void)
+{
+ errno = EWOULDBLOCK;
+ ACE_ERROR ((LM_DEBUG,
+ "would block\n"));
+}
+
+int
+ACE_TMAIN (int argc, ACE_TCHAR *argv[])
+{
+ int counter = 1;
+
+ if (argc > 1) // Just give a dummy command-line argument to trigger this path.
+ {
+ if (ACE_LOG_MSG->open (argv[0],
+ ACE_Log_Msg::OSTREAM) == -1)
+ ACE_ERROR ((LM_ERROR,
+ "cannot open logger!!!\n"));
+
+ cause_error ();
+ // Check to see what happened.
+ if (ACE_LOG_MSG->op_status () == -1
+ && ACE_LOG_MSG->errnum () == EWOULDBLOCK)
+ ACE_DEBUG ((LM_DEBUG,
+ "op_status and errnum work!\n"));
+ else
+ ACE_ERROR ((LM_ERROR,
+ "op_status and errnum failed!\n"));
+ }
+ else // The default behavior is to log to STDERR...
+ {
+ if (ACE_LOG_MSG->open (argv[0]) == -1)
+ ACE_ERROR ((LM_ERROR,
+ "cannot open logger!!!\n"));
+
+ cause_error ();
+
+ // Check to see what happened.
+ if (ACE_LOG_MSG->op_status () == -1
+ && ACE_LOG_MSG->errnum () == EWOULDBLOCK)
+ ACE_DEBUG ((LM_DEBUG,
+ "op_status and errnum work!\n"));
+ else
+ ACE_ERROR ((LM_ERROR,
+ "op_status and errnum failed!\n"));
+
+ // Exercise many different combinations of STDERR and OSTREAM.
+
+ double f = 3.1416 * counter++;
+ int i = 10000;
+
+ ACE_DEBUG ((LM_INFO,
+ "%10f, %*s%s = %d\n",
+ f,
+ 8,
+ "",
+ "hello",
+ i));
+
+#if !defined (ACE_LACKS_IOSTREAM_TOTALLY)
+
+ ACE_LOG_MSG->set_flags (ACE_Log_Msg::OSTREAM);
+ ACE_LOG_MSG->msg_ostream (&cout);
+
+ f = 3.1416 * counter;
+ i = 10000 * counter++;
+
+ // This message will print twice - once for OSTREAM and once for
+ // STDERR.
+
+ ACE_DEBUG ((LM_INFO,
+ "%10f, %*s%s = %d\n",
+ f,
+ 8,
+ "",
+ "world",
+ i));
+
+ ACE_LOG_MSG->clr_flags (ACE_Log_Msg::STDERR);
+
+ f = 3.1416 * counter;
+ i = 10000 * counter++;
+
+ ACE_DEBUG ((LM_INFO,
+ "%10f, %*s%s = %d\n",
+ f,
+ 8,
+ "",
+ "world",
+ i));
+
+ ACE_LOG_MSG->msg_ostream (0);
+
+ ACE_LOG_MSG->set_flags (ACE_Log_Msg::STDERR);
+
+ f = 3.1416 * counter;
+ i = 10000 * counter++;
+
+ ACE_DEBUG ((LM_INFO,
+ "%10f, %*s%s = %d\n",
+ f,
+ 8,
+ "",
+ "world",
+ i));
+
+ ACE_LOG_MSG->clr_flags (ACE_Log_Msg::OSTREAM);
+ ACE_LOG_MSG->msg_ostream (&cerr);
+
+ f = 3.1416 * counter;
+ i = 10000 * counter++;
+
+ ACE_DEBUG ((LM_INFO,
+ "%10f, %*s%s = %d\n",
+ f,
+ 8,
+ "",
+ "world",
+ i));
+
+#endif /* !defined (ACE_LACKS_IOSTREAM_TOTALLY) */
+
+ static int array[] = {1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048};
+
+ // Print out the binary bytes of the array in hex form.
+ ACE_LOG_MSG->log_hexdump (LM_DEBUG,
+ (char *) array,
+ sizeof array);
+
+ // Disable the LM_DEBUG and LM_INFO messages at the process level.
+ u_long priority_mask =
+ ACE_LOG_MSG->priority_mask (ACE_Log_Msg::PROCESS);
+ ACE_CLR_BITS (priority_mask,
+ LM_DEBUG | LM_INFO);
+ ACE_LOG_MSG->priority_mask (priority_mask,
+ ACE_Log_Msg::PROCESS);
+
+ ACE_DEBUG ((LM_INFO,
+ "This LM_INFO message should not print!\n"));
+ ACE_DEBUG ((LM_DEBUG,
+ "This LM_DEBUG message should not print!\n"));
+
+ ACE_SET_BITS (priority_mask,
+ LM_INFO);
+ ACE_LOG_MSG->priority_mask (priority_mask,
+ ACE_Log_Msg::PROCESS);
+
+ ACE_DEBUG ((LM_INFO,
+ "This LM_INFO message should print!\n"));
+ ACE_DEBUG ((LM_DEBUG,
+ "This LM_DEBUG message should not print!\n"));
+
+ ACE_CLR_BITS (priority_mask, LM_INFO);
+ ACE_LOG_MSG->priority_mask (priority_mask,
+ ACE_Log_Msg::PROCESS);
+
+ ACE_DEBUG ((LM_INFO,
+ "This LM_INFO message should not print!\n"));
+ ACE_DEBUG ((LM_DEBUG,
+ "This LM_DEBUG message should not print!\n"));
+
+ char badname[] = "badname";
+
+ char *l_argv[2];
+ l_argv[0] = badname;
+ l_argv[1] = 0;
+
+ if (ACE_OS::execv (badname,
+ l_argv) == -1)
+ {
+ ACE_ERROR ((LM_ERROR,
+ "%n: (%x), %p%r\n",
+ 10000,
+ badname,
+ cleanup));
+ ACE_OS::_exit ();
+ }
+ }
+ return 0;
+}
diff --git a/ACE/examples/Log_Msg/test_ostream.cpp b/ACE/examples/Log_Msg/test_ostream.cpp
new file mode 100644
index 00000000000..3492195fe9d
--- /dev/null
+++ b/ACE/examples/Log_Msg/test_ostream.cpp
@@ -0,0 +1,89 @@
+// $Id$
+
+// ============================================================================
+//
+// = LIBRARY
+// examples/Log_Msg
+//
+// = FILENAME
+// test_ostream.cpp
+//
+// = DESCRIPTION
+// This program tests the Log_Msg abstraction wrt writing to
+// stderr and to a file.
+//
+// = AUTHOR
+// Irfan Pyarali <irfan@cse.wustl.edu>
+//
+// ============================================================================
+
+#include "ace/OS_main.h"
+
+// FUZZ: disable check_for_streams_include
+#include "ace/streams.h"
+
+#include "ace/Log_Msg.h"
+
+ACE_RCSID(Log_Msg, test_ostream, "$Id$")
+
+int
+ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ // This message should show up in stderr.
+ ACE_DEBUG ((LM_DEBUG,
+ "first message\n"));
+
+ ACE_LOG_MSG->clr_flags (ACE_Log_Msg::STDERR);
+
+ // This message should not show up anywhere.
+ ACE_DEBUG ((LM_DEBUG,
+ "second message\n"));
+
+ ACE_LOG_MSG->set_flags (ACE_Log_Msg::OSTREAM);
+
+ // This message should not show up anywhere since no ostream has
+ // been specified.
+ ACE_DEBUG ((LM_DEBUG,
+ "third message\n"));
+
+#if !defined (ACE_LACKS_IOSTREAM_TOTALLY)
+ // Create a persistent store.
+ const char *filename = "output";
+ ofstream outfile (filename, ios::out | ios::trunc);
+
+ // Check for errors.
+ if (outfile.bad ())
+ return 1;
+
+ // Set the ostream.
+ ACE_LOG_MSG->msg_ostream (&outfile);
+
+ // This message should show up in the ostream.
+ ACE_DEBUG ((LM_DEBUG,
+ "fourth message\n"));
+#endif /* ACE_LACKS_IOSTREAM_TOTALLY */
+
+ ACE_LOG_MSG->set_flags (ACE_Log_Msg::STDERR);
+
+ // This message should show up in stderr and the ostream (without
+ // ACE_LACKS_IOSTREAM_TOTALLY).
+ ACE_DEBUG ((LM_DEBUG,
+ "fifth message\n"));
+
+#if !defined (ACE_LACKS_IOSTREAM_TOTALLY)
+ ifstream infile (filename, ios::in);
+
+ if (infile.bad ())
+ return 1;
+
+ // This loop should print out the contents of file "output", which should
+ // have the strings "fourth\n" and "fifth\n" in them.
+
+ char line[BUFSIZ];
+
+ while (infile.getline (line, BUFSIZ, '\n'))
+ std::cout << line << std::endl;
+
+#endif /* ACE_LACKS_IOSTREAM_TOTALLY */
+ return 0;
+}
diff --git a/ACE/examples/Logger/Acceptor-server/.cvsignore b/ACE/examples/Logger/Acceptor-server/.cvsignore
new file mode 100644
index 00000000000..76c31d8c56f
--- /dev/null
+++ b/ACE/examples/Logger/Acceptor-server/.cvsignore
@@ -0,0 +1,2 @@
+server_loggerd
+server_loggerd
diff --git a/ACE/examples/Logger/Acceptor-server/Logger_Acceptor_Server.mpc b/ACE/examples/Logger/Acceptor-server/Logger_Acceptor_Server.mpc
new file mode 100644
index 00000000000..1e4d8240e38
--- /dev/null
+++ b/ACE/examples/Logger/Acceptor-server/Logger_Acceptor_Server.mpc
@@ -0,0 +1,6 @@
+// -*- MPC -*-
+// $Id$
+
+project : aceexe {
+ exename = server_loggerd
+} \ No newline at end of file
diff --git a/ACE/examples/Logger/Acceptor-server/Makefile.am b/ACE/examples/Logger/Acceptor-server/Makefile.am
new file mode 100644
index 00000000000..bf1824c86d3
--- /dev/null
+++ b/ACE/examples/Logger/Acceptor-server/Makefile.am
@@ -0,0 +1,34 @@
+## Process this file with automake to create Makefile.in
+##
+## $Id$
+##
+## This file was generated by MPC. Any changes made directly to
+## this file will be lost the next time it is generated.
+##
+## MPC Command:
+## /acebuilds/ACE_wrappers-repository/bin/mwc.pl -include /acebuilds/MPC/config -include /acebuilds/MPC/templates -feature_file /acebuilds/ACE_wrappers-repository/local.features -noreldefs -type automake -exclude build,Kokyu
+
+ACE_BUILDDIR = $(top_builddir)
+ACE_ROOT = $(top_srcdir)
+
+## Makefile.Logger_Acceptor_Server.am
+noinst_PROGRAMS = server_loggerd
+
+server_loggerd_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+server_loggerd_SOURCES = \
+ server_loggerd.cpp \
+ server_loggerd.h
+
+server_loggerd_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Clean up template repositories, etc.
+clean-local:
+ -rm -f *~ *.bak *.rpo *.sym lib*.*_pure_* core core.*
+ -rm -f gcctemp.c gcctemp so_locations *.ics
+ -rm -rf cxx_repository ptrepository ti_files
+ -rm -rf templateregistry ir.out
+ -rm -rf ptrepository SunWS_cache Templates.DB
diff --git a/ACE/examples/Logger/Acceptor-server/server_loggerd.cpp b/ACE/examples/Logger/Acceptor-server/server_loggerd.cpp
new file mode 100644
index 00000000000..fac6447d898
--- /dev/null
+++ b/ACE/examples/Logger/Acceptor-server/server_loggerd.cpp
@@ -0,0 +1,241 @@
+// $Id$
+// server_loggerd.cpp,v 4.29 2003/12/30 23:18:59 shuston Exp
+
+// This server daemon collects, formats, and displays logging
+// information forwarded from client daemons running on other hosts in
+// the network. In addition, this example illustrates how to use the
+// ACE_Reactor, ACE_Acceptor, ACE_Singleton, and the ACE_Test_and_Set
+// components.
+
+#include "ace/OS_NS_string.h"
+#include "ace/Get_Opt.h"
+#include "ace/Acceptor.h"
+#include "ace/Null_Mutex.h"
+#include "ace/SOCK_Acceptor.h"
+#include "ace/Singleton.h"
+#include "ace/Test_and_Set.h"
+
+// FUZZ: disable check_for_streams_include
+#include "ace/streams.h"
+
+#include "ace/Log_Record.h"
+#include "ace/Test_and_Set.h"
+
+#include "server_loggerd.h"
+
+ACE_RCSID(Acceptor_server, server_loggerd, "$Id$")
+
+// ----------------------------------------
+
+// Return the port number.
+
+u_short
+Options::port (void)
+{
+ return this->port_;
+}
+
+// Parse the command-line options.
+
+void
+Options::parse_args (int argc, ACE_TCHAR *argv[])
+{
+ this->port_ = ACE_DEFAULT_SERVER_PORT;
+
+ ACE_Get_Opt get_opt (argc, argv, ACE_TEXT ("p:"));
+
+ for (int c; (c = get_opt ()) != -1; )
+ switch (c)
+ {
+ case 'p':
+ this->port_ = ACE_OS::atoi (get_opt.opt_arg ());
+ break;
+ default:
+ break;
+ }
+}
+
+// ----------------------------------------
+
+// Our Reactor Singleton.
+typedef ACE_Singleton<ACE_Reactor, ACE_Null_Mutex>
+REACTOR;
+
+// Our Options Singleton.
+typedef ACE_Singleton<Options, ACE_Null_Mutex>
+OPTIONS;
+
+// Our ACE_Test_and_Set Singleton.
+typedef ACE_Singleton<ACE_Test_and_Set <ACE_Null_Mutex, sig_atomic_t>, ACE_Null_Mutex>
+QUIT_HANDLER;
+
+// ----------------------------------------
+
+// Specialize a Logging Acceptor.
+typedef ACE_Acceptor <Logging_Handler, ACE_SOCK_ACCEPTOR>
+Logging_Acceptor;
+
+// Default constructor.
+
+Logging_Handler::Logging_Handler (void)
+{
+}
+
+int
+Logging_Handler::handle_timeout (const ACE_Time_Value &,
+ const void *arg)
+{
+#if defined (ACE_NDEBUG)
+ ACE_UNUSED_ARG (arg);
+#endif /* ACE_NDEBUG */
+
+ ACE_ASSERT (arg == this);
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("(%P|%t) handling timeout from this = %@\n"), this));
+ return 0;
+}
+
+// Perform the logging record receive.
+
+int
+Logging_Handler::handle_input (ACE_HANDLE)
+{
+ // Perform two recv's to emulate record-oriented semantics. Note
+ // that this code is not entirely portable since it relies on the
+ // fact that sizeof (ssize_t) is the same on both the sender and
+ // receiver side. To correctly handle this is painful, and we leave
+ // it as an exercise for the reader ;-).
+
+ ssize_t len;
+ ssize_t n = this->peer ().recv ((void *) &len, sizeof len);
+
+ switch (n)
+ {
+ case -1:
+ ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("(%P|%t) %p at host %C\n"),
+ ACE_TEXT ("client logger"), this->peer_name_), -1);
+ /* NOTREACHED */
+ case 0:
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("(%P|%t) closing log daemon at host %C (fd = %d)\n"),
+ this->peer_name_, this->get_handle ()), -1);
+ /* NOTREACHED */
+ case sizeof (size_t):
+ {
+ ACE_Log_Record lp;
+
+ len = ntohl (len);
+ n = this->peer ().recv_n ((void *) &lp, len);
+
+ if (n != len)
+ ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("(%P|%t) %p at host %C\n"),
+ ACE_TEXT ("client logger"), this->peer_name_),-1);
+ /* NOTREACHED */
+
+ lp.decode ();
+
+ if (lp.length () == n)
+ {
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("(%P|%t) ")));
+#if !defined (ACE_LACKS_IOSTREAM_TOTALLY)
+ lp.print (ACE_TEXT_CHAR_TO_TCHAR (this->peer_name_), 1, cerr);
+#else
+ lp.print (ACE_TEXT_CHAR_TO_TCHAR (this->peer_name_), 1, stderr);
+#endif
+ }
+ else
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("(%P|%t) error, lp.length = %d, n = %d\n"),
+ lp.length (), n));
+ break;
+ }
+ default:
+ ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("(%P|%t) %p at host %C\n"),
+ ACE_TEXT ("client logger"), this->peer_name_), -1);
+ /* NOTREACHED */
+ }
+
+ return 0;
+}
+
+int
+Logging_Handler::open (void *)
+{
+ ACE_INET_Addr addr;
+
+ if (this->peer ().get_remote_addr (addr) == -1)
+ return -1;
+ else
+ {
+ ACE_OS::strncpy (this->peer_name_,
+ addr.get_host_name (),
+ MAXHOSTNAMELEN + 1);
+
+ if (REACTOR::instance ()->register_handler (this, READ_MASK) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("(%P|%t) can't register with reactor\n")),
+ -1);
+ else if (REACTOR::instance ()->schedule_timer
+ (this,
+ (const void *) this,
+ ACE_Time_Value (2),
+ ACE_Time_Value (2)) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("(%P|%t) can't register with reactor\n")),
+ -1);
+ else
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("(%P|%t) connected with %C\n"),
+ this->peer_name_));
+ return 0;
+ }
+}
+
+int
+ACE_TMAIN (int argc, ACE_TCHAR *argv[])
+{
+ // Acceptor factory.
+ Logging_Acceptor peer_acceptor;
+
+ OPTIONS::instance ()->parse_args (argc, argv);
+
+ // We need to pass in REACTOR::instance () here so that we don't use
+ // the default ACE_Reactor::instance ().
+
+ if (peer_acceptor.open
+ (ACE_INET_Addr (OPTIONS::instance ()->port ()),
+ REACTOR::instance ()) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("%p\n"), ACE_TEXT ("open")), -1);
+
+ // Register QUIT_HANDLER to receive SIGINT commands. When received,
+ // QUIT_HANDLER becomes "set" and thus, the event loop below will
+ // exit.
+ else if (REACTOR::instance ()->register_handler
+ (SIGINT, QUIT_HANDLER::instance ()) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("registering service with ACE_Reactor\n")),
+ -1);
+
+ // Run forever, performing logging service.
+
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("(%P|%t) starting up server logging daemon\n")));
+
+ // Perform logging service until QUIT_HANDLER receives SIGINT.
+ while (QUIT_HANDLER::instance ()->is_set () == 0)
+ REACTOR::instance ()->handle_events ();
+
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("(%P|%t) shutting down server logging daemon\n")));
+
+ return 0;
+}
+
+#if defined (ACE_HAS_EXPLICIT_STATIC_TEMPLATE_MEMBER_INSTANTIATION)
+template ACE_Singleton<ACE_Reactor, ACE_Null_Mutex> *
+ ACE_Singleton<ACE_Reactor, ACE_Null_Mutex>::singleton_;
+template ACE_Singleton<Options, ACE_Null_Mutex> *
+ ACE_Singleton<Options, ACE_Null_Mutex>::singleton_;
+template ACE_Singleton<ACE_Test_and_Set <ACE_Null_Mutex, sig_atomic_t>, ACE_Null_Mutex> *
+ ACE_Singleton<ACE_Test_and_Set <ACE_Null_Mutex, sig_atomic_t>, ACE_Null_Mutex>::singleton_;
+#endif /* ACE_HAS_EXPLICIT_STATIC_TEMPLATE_MEMBER_INSTANTIATION */
diff --git a/ACE/examples/Logger/Acceptor-server/server_loggerd.h b/ACE/examples/Logger/Acceptor-server/server_loggerd.h
new file mode 100644
index 00000000000..33d5f0042ee
--- /dev/null
+++ b/ACE/examples/Logger/Acceptor-server/server_loggerd.h
@@ -0,0 +1,54 @@
+// $Id$
+
+// Define classes used with templates in server_loggerd.h.
+
+#ifndef __SERVER_LOGGERD_H
+#define __SERVER_LOGGERD_H
+
+#include "ace/SOCK_Stream.h"
+#include "ace/Svc_Handler.h"
+#include "ace/os_include/os_netdb.h"
+
+class Options
+{
+ // = TITLE
+ // Keeps track of the options.
+public:
+ void parse_args (int argc, ACE_TCHAR *argv[]);
+ u_short port (void);
+
+private:
+ u_short port_;
+ // Port number;
+};
+
+
+class Logging_Handler : public ACE_Svc_Handler<ACE_SOCK_STREAM, ACE_NULL_SYNCH>
+// = TITLE
+// Receive client message from the remote clients.
+//
+// = DESCRIPTION
+// This class demonstrates how to receive messages from remote
+// clients using the notification mechanisms in the
+// <ACE_Reactor>. In addition, it also illustrates how to
+// utilize the <ACE_Reactor> timer mechanisms, as well.
+{
+public:
+ // = Initialization and termination methods.
+ Logging_Handler (void);
+
+ // = Hooks for opening and closing handlers.
+ virtual int open (void *);
+
+protected:
+ // = Demultiplexing hooks.
+ virtual int handle_input (ACE_HANDLE);
+ virtual int handle_timeout (const ACE_Time_Value &tv,
+ const void *arg);
+
+private:
+ char peer_name_[MAXHOSTNAMELEN + 1];
+ // Host we are connected to.
+};
+
+#endif /* __SERVER_LOGGERD_H */
diff --git a/ACE/examples/Logger/Makefile.am b/ACE/examples/Logger/Makefile.am
new file mode 100644
index 00000000000..3aa67282ba4
--- /dev/null
+++ b/ACE/examples/Logger/Makefile.am
@@ -0,0 +1,15 @@
+## Process this file with automake to create Makefile.in
+##
+## $Id$
+##
+## This file was generated by MPC. Any changes made directly to
+## this file will be lost the next time it is generated.
+##
+## MPC Command:
+## /acebuilds/ACE_wrappers-repository/bin/mwc.pl -include /acebuilds/MPC/config -include /acebuilds/MPC/templates -feature_file /acebuilds/ACE_wrappers-repository/local.features -noreldefs -type automake -exclude build,Kokyu
+
+SUBDIRS = \
+ Acceptor-server \
+ client \
+ simple-server
+
diff --git a/ACE/examples/Logger/README b/ACE/examples/Logger/README
new file mode 100644
index 00000000000..bac9aa1d127
--- /dev/null
+++ b/ACE/examples/Logger/README
@@ -0,0 +1,32 @@
+This directory contains a simple client/server implementation of the
+distributed logging server described in several papers in the C++
+Report (which can be obtained via the following WWW URLs:
+http://www.cs.wustl.edu/~schmidt/{Reactor1-93.ps.gz,Reactor2-93.ps.gz}).
+
+The example consists of the following directories:
+
+ . client
+
+ This program talks directly to the server logging
+ daemon. The server daemon must be started before you
+ can run this test.
+
+ . simple-server
+
+ This program runs a simple, non-templated,
+ single-threaded Reactive implementation of the
+ distributed logging server daemon.
+
+ . Acceptor-server
+
+ This program runs templated, Acceptor-based
+ single-threaded Reactive implementation of the
+ distributed logging server daemon.
+
+To see a more complex solution that implements the design described in
+the C++ Report articles, please see the:
+
+$ACE_ROOT/netsvcs/{clients,lib,servers}
+
+directories.
+
diff --git a/ACE/examples/Logger/client/.cvsignore b/ACE/examples/Logger/client/.cvsignore
new file mode 100644
index 00000000000..6c538132cc9
--- /dev/null
+++ b/ACE/examples/Logger/client/.cvsignore
@@ -0,0 +1,2 @@
+logging_app
+logging_app
diff --git a/ACE/examples/Logger/client/Logger_client.mpc b/ACE/examples/Logger/client/Logger_client.mpc
new file mode 100644
index 00000000000..ec75f197b14
--- /dev/null
+++ b/ACE/examples/Logger/client/Logger_client.mpc
@@ -0,0 +1,6 @@
+// -*- MPC -*-
+// $Id$
+
+project : aceexe {
+ exename = logging_app
+} \ No newline at end of file
diff --git a/ACE/examples/Logger/client/Makefile.am b/ACE/examples/Logger/client/Makefile.am
new file mode 100644
index 00000000000..d38d5699588
--- /dev/null
+++ b/ACE/examples/Logger/client/Makefile.am
@@ -0,0 +1,33 @@
+## Process this file with automake to create Makefile.in
+##
+## $Id$
+##
+## This file was generated by MPC. Any changes made directly to
+## this file will be lost the next time it is generated.
+##
+## MPC Command:
+## /acebuilds/ACE_wrappers-repository/bin/mwc.pl -include /acebuilds/MPC/config -include /acebuilds/MPC/templates -feature_file /acebuilds/ACE_wrappers-repository/local.features -noreldefs -type automake -exclude build,Kokyu
+
+ACE_BUILDDIR = $(top_builddir)
+ACE_ROOT = $(top_srcdir)
+
+## Makefile.Logger_client.am
+noinst_PROGRAMS = logging_app
+
+logging_app_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+logging_app_SOURCES = \
+ logging_app.cpp
+
+logging_app_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Clean up template repositories, etc.
+clean-local:
+ -rm -f *~ *.bak *.rpo *.sym lib*.*_pure_* core core.*
+ -rm -f gcctemp.c gcctemp so_locations *.ics
+ -rm -rf cxx_repository ptrepository ti_files
+ -rm -rf templateregistry ir.out
+ -rm -rf ptrepository SunWS_cache Templates.DB
diff --git a/ACE/examples/Logger/client/logging_app.cpp b/ACE/examples/Logger/client/logging_app.cpp
new file mode 100644
index 00000000000..ba5bb24295e
--- /dev/null
+++ b/ACE/examples/Logger/client/logging_app.cpp
@@ -0,0 +1,59 @@
+// $Id$
+
+// This program sends logging records directly to the server, rather
+// than going through the client logging daemon.
+
+#include "ace/SOCK_Connector.h"
+#include "ace/Log_Record.h"
+#include "ace/Log_Msg.h"
+#include "ace/OS_NS_time.h"
+#include "ace/OS_NS_stdio.h"
+#include "ace/OS_NS_stdlib.h"
+#include "ace/OS_NS_unistd.h"
+
+ACE_RCSID(client, logging_app, "$Id$")
+
+static u_short LOGGER_PORT = ACE_DEFAULT_SERVER_PORT;
+static const ACE_TCHAR *const LOGGER_HOST = ACE_DEFAULT_SERVER_HOST;
+static const int MAX_ITERATIONS = 10;
+
+int
+ACE_TMAIN (int argc, ACE_TCHAR *argv[])
+{
+ const ACE_TCHAR *logger_host = argc > 1 ? argv[1] : LOGGER_HOST;
+ u_short logger_port = argc > 2 ? ACE_OS::atoi (argv[2]) : LOGGER_PORT;
+ int max_iterations = argc > 3 ? ACE_OS::atoi (argv[3]) : MAX_ITERATIONS;
+
+ ACE_SOCK_Stream logger;
+ ACE_SOCK_Connector connector;
+ ACE_INET_Addr addr (logger_port, logger_host);
+
+ if (connector.connect (logger, addr) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("%p\n"), ACE_TEXT ("open")), -1);
+
+ for (int i = 0; i < max_iterations; i++)
+ {
+ ACE_Log_Record log_record (LM_DEBUG,
+ ACE_OS::time ((time_t *) 0),
+ ACE_OS::getpid ());
+
+ ACE_TCHAR buf[BUFSIZ];
+ ACE_OS::sprintf (buf, ACE_TEXT ("message = %d\n"), i + 1);
+ log_record.msg_data (buf);
+ size_t len = log_record.length ();
+ size_t encoded_len = htonl (len);
+
+ log_record.encode ();
+
+ if (logger.send (4, &encoded_len, sizeof encoded_len,
+ (char *) &log_record, len) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("%p\n"), ACE_TEXT ("send")),-1);
+ else
+ ACE_OS::sleep (1);
+ }
+
+ if (logger.close () == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("%p\n"), ACE_TEXT ("close")), -1);
+
+ return 0;
+}
diff --git a/ACE/examples/Logger/simple-server/.cvsignore b/ACE/examples/Logger/simple-server/.cvsignore
new file mode 100644
index 00000000000..76c31d8c56f
--- /dev/null
+++ b/ACE/examples/Logger/simple-server/.cvsignore
@@ -0,0 +1,2 @@
+server_loggerd
+server_loggerd
diff --git a/ACE/examples/Logger/simple-server/Logger_Simple_Server.mpc b/ACE/examples/Logger/simple-server/Logger_Simple_Server.mpc
new file mode 100644
index 00000000000..1e4d8240e38
--- /dev/null
+++ b/ACE/examples/Logger/simple-server/Logger_Simple_Server.mpc
@@ -0,0 +1,6 @@
+// -*- MPC -*-
+// $Id$
+
+project : aceexe {
+ exename = server_loggerd
+} \ No newline at end of file
diff --git a/ACE/examples/Logger/simple-server/Logging_Acceptor.cpp b/ACE/examples/Logger/simple-server/Logging_Acceptor.cpp
new file mode 100644
index 00000000000..7e5e0d0075c
--- /dev/null
+++ b/ACE/examples/Logger/simple-server/Logging_Acceptor.cpp
@@ -0,0 +1,85 @@
+// $Id$
+
+#include "ace/WFMO_Reactor.h"
+#include "ace/Log_Msg.h"
+
+#include "Logging_Acceptor.h"
+#include "Logging_Handler.h"
+#include "Reactor_Singleton.h"
+
+ACE_RCSID(simple_server, Logging_Acceptor, "$Id$")
+
+// Initialize peer_acceptor object.
+
+int
+Logging_Acceptor::open (const ACE_INET_Addr &addr)
+{
+ // Reuse addr if already in use.
+ if (this->peer_acceptor_.open (addr, 1) == -1)
+ return -1;
+ else
+ return 0;
+}
+
+// Default constructor.
+
+Logging_Acceptor::Logging_Acceptor (void)
+{
+}
+
+// Performs termination activities.
+
+int
+Logging_Acceptor::handle_close (ACE_HANDLE, ACE_Reactor_Mask)
+{
+ this->peer_acceptor_.close ();
+ // Note, this object MUST be allocated dynamically!
+ delete this;
+ return 0;
+}
+
+Logging_Acceptor::~Logging_Acceptor (void)
+{
+}
+
+// Returns underlying device descriptor.
+
+ACE_HANDLE
+Logging_Acceptor::get_handle (void) const
+{
+ return this->peer_acceptor_.get_handle ();
+}
+
+// Accepts connections from client and registers new object with the
+// ACE_Reactor.
+
+int
+Logging_Acceptor::handle_input (ACE_HANDLE)
+{
+ Logging_Handler *svc_handler;
+
+ ACE_NEW_RETURN (svc_handler, Logging_Handler, -1);
+
+ // Accept the connection from a client client daemon.
+
+ // Try to find out if the implementation of the reactor that we are
+ // using requires us to reset the event association for the newly
+ // created handle. This is because the newly created handle will
+ // inherit the properties of the listen handle, including its event
+ // associations.
+ int reset_new_handle = this->reactor ()->uses_event_associations ();
+
+ if (this->peer_acceptor_.accept (svc_handler->peer (), // stream
+ 0, // remote address
+ 0, // timeout
+ 1, // restart
+ reset_new_handle // reset new handler
+ ) == -1
+ || svc_handler->open () == -1)
+ {
+ svc_handler->close ();
+ ACE_ERROR_RETURN ((LM_ERROR, "%p", "accept/open failed"), -1);
+ }
+
+ return 0;
+}
diff --git a/ACE/examples/Logger/simple-server/Logging_Acceptor.h b/ACE/examples/Logger/simple-server/Logging_Acceptor.h
new file mode 100644
index 00000000000..0424a7c3889
--- /dev/null
+++ b/ACE/examples/Logger/simple-server/Logging_Acceptor.h
@@ -0,0 +1,59 @@
+/* -*- C++ -*- */
+// $Id$
+
+// ============================================================================
+//
+// = LIBRARY
+// examples
+//
+// = FILENAME
+// Logging_Acceptor.h
+//
+// = AUTHOR
+// Doug Schmidt
+//
+// ============================================================================
+
+#ifndef _CLIENT_ACCEPTOR_H
+#define _CLIENT_ACCEPTOR_H
+
+#include "ace/SOCK_Acceptor.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/Event_Handler.h"
+
+class Logging_Acceptor : public ACE_Event_Handler
+ // = TITLE
+ // Handle connection requests from remote client clients.
+ //
+ // = DESCRIPTION
+ // Accepts client connection requests, creates Logging_Handler's
+ // to process them, and registers these Handlers with the
+ // ACE_Reactor Singleton.
+{
+friend class Logging_Handler;
+public:
+ Logging_Acceptor (void);
+ // Constructor.
+
+ int open (const ACE_INET_Addr &a);
+ // Initialization.
+
+private:
+ // = Demuxing hooks.
+ virtual int handle_input (ACE_HANDLE);
+ virtual int handle_close (ACE_HANDLE, ACE_Reactor_Mask);
+ virtual ACE_HANDLE get_handle (void) const;
+
+ ~Logging_Acceptor (void);
+ // By making this private we ensure that the <Logging_Acceptor> is
+ // allocated dynamically.
+
+ ACE_SOCK_Acceptor peer_acceptor_;
+ // Passive connection acceptor factory.
+};
+
+#endif /* _CLIENT_ACCEPTOR_H */
diff --git a/ACE/examples/Logger/simple-server/Logging_Handler.cpp b/ACE/examples/Logger/simple-server/Logging_Handler.cpp
new file mode 100644
index 00000000000..111a26248fc
--- /dev/null
+++ b/ACE/examples/Logger/simple-server/Logging_Handler.cpp
@@ -0,0 +1,164 @@
+// $Id$
+
+#include "ace/Log_Msg.h"
+
+#include "Logging_Handler.h"
+#include "Reactor_Singleton.h"
+#include "ace/Log_Record.h"
+#include "ace/OS_NS_string.h"
+
+ACE_RCSID(simple_server, Logging_Handler, "$Id$")
+
+// Default constructor.
+
+Logging_Handler::Logging_Handler (void)
+{
+}
+
+Logging_Handler::~Logging_Handler (void)
+{
+ // Make sure there are no timers.
+ REACTOR::instance ()->cancel_timer (this);
+
+ this->cli_stream_.close ();
+}
+
+// Extract the underlying ACE_SOCK_Stream (e.g., for purposes of
+// accept()).
+
+ACE_SOCK_Stream &
+Logging_Handler::peer (void)
+{
+ return this->cli_stream_;
+}
+
+int
+Logging_Handler::handle_timeout (const ACE_Time_Value &,
+ const void *arg)
+{
+#if defined (ACE_NDEBUG)
+ ACE_UNUSED_ARG (arg);
+#endif /* ACE_NDEBUG */
+
+ ACE_ASSERT (arg == this);
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("(%P|%t) handling timeout from this = %@\n"),
+ this));
+ return 0;
+}
+
+// Perform the logging record receive.
+
+int
+Logging_Handler::handle_input (ACE_HANDLE)
+{
+ ssize_t n;
+ size_t len;
+
+ // Perform two recv's to emulate record-oriented semantics. Note
+ // that this code is not entirely portable since it relies on the
+ // fact that sizeof (ssize_t) is the same on both the sender and
+ // receiver side. To correctly handle this is painful, and we leave
+ // it as an exercise for the reader ;-).
+
+ switch (n = this->cli_stream_.recv ((void *) &len, sizeof len))
+ {
+ case -1:
+ ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("(%P|%t) %p at host %C\n"),
+ ACE_TEXT ("client logger"), this->host_name_), -1);
+ /* NOTREACHED */
+ case 0:
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "(%P|%t) closing log daemon at host %s (fd = %d)\n",
+ this->host_name_, this->get_handle ()), -1);
+ /* NOTREACHED */
+ case sizeof (size_t):
+ {
+ ACE_Log_Record lp;
+
+ len = ntohl (len);
+ n = this->cli_stream_.recv_n ((void *) &lp, len);
+ if (n != (ssize_t) len)
+ ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("(%P|%t) %p at host %C\n"),
+ ACE_TEXT ("client logger"), this->host_name_), -1);
+ /* NOTREACHED */
+
+ lp.decode ();
+
+ if (lp.length () == n)
+ {
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("(%P|%t) ")));
+ lp.print (ACE_TEXT_CHAR_TO_TCHAR (this->host_name_), 1);
+ }
+ else
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("(%P|%t) error, lp.length = %d, n = %d\n"),
+ lp.length (), n));
+ break;
+ }
+ default:
+ ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("(%P|%t) %p at host %C\n"),
+ ACE_TEXT ("client logger"), this->host_name_), -1);
+ /* NOTREACHED */
+ }
+
+ return 0;
+}
+
+// Extract underlying device descriptor.
+
+ACE_HANDLE
+Logging_Handler::get_handle (void) const
+{
+ return this->cli_stream_.get_handle ();
+}
+
+int
+Logging_Handler::open (void)
+{
+ ACE_INET_Addr addr;
+
+ if (this->cli_stream_.get_remote_addr (addr) == -1)
+ return -1;
+ else
+ {
+ ACE_OS::strncpy (this->host_name_,
+ addr.get_host_name (),
+ MAXHOSTNAMELEN + 1);
+
+ if (REACTOR::instance ()->register_handler (this, READ_MASK) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("(%P|%t) can't register with reactor\n")),
+ -1);
+ else if (REACTOR::instance ()->schedule_timer
+ (this, (const void *) this,
+ ACE_Time_Value (2),
+ ACE_Time_Value (2)) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("(%P|%t) can't register with reactor\n")),
+ -1);
+ else
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("(%P|%t) connected with %C\n"),
+ this->host_name_));
+ return 0;
+ }
+}
+
+// Perform termination activities when deregistered from the
+// ACE_Reactor.
+
+int
+Logging_Handler::handle_close (ACE_HANDLE, ACE_Reactor_Mask)
+{
+ // Must have been allocated dynamically
+ delete this;
+ return 0;
+}
+
+// Perform termination activities when close fails.
+
+int
+Logging_Handler::close (void)
+{
+ return this->handle_close ();
+}
diff --git a/ACE/examples/Logger/simple-server/Logging_Handler.h b/ACE/examples/Logger/simple-server/Logging_Handler.h
new file mode 100644
index 00000000000..633e04a167c
--- /dev/null
+++ b/ACE/examples/Logger/simple-server/Logging_Handler.h
@@ -0,0 +1,71 @@
+/* -*- C++ -*- */
+// $Id$
+
+
+// ============================================================================
+//
+// = LIBRARY
+// examples
+//
+// = FILENAME
+// Logging_Handler.h
+//
+// = AUTHOR
+// Doug Schmidt
+//
+// ============================================================================
+
+#ifndef _CLIENT_HANDLER_H
+#define _CLIENT_HANDLER_H
+
+#include "ace/Event_Handler.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/INET_Addr.h"
+#include "ace/SOCK_Stream.h"
+#include "ace/os_include/os_netdb.h"
+
+class Logging_Handler : public ACE_Event_Handler
+ // = TITLE
+ // Receive client message from the remote clients.
+ //
+ // = DESCRIPTION
+ // This class demonstrates how to receive messages from remote
+ // clients using the notification mechanisms in the
+ // <ACE_Reactor>. In addition, it also illustrates how to
+ // utilize the <ACE_Reactor> timer mechanisms, as well.
+{
+public:
+ Logging_Handler (void);
+
+ // = Hooks for opening and closing handlers.
+ virtual int open (void);
+ virtual int close (void);
+
+ ACE_SOCK_Stream &peer (void);
+ // Conversion operators.
+
+protected:
+ // = Demultiplexing hooks.
+ virtual ACE_HANDLE get_handle (void) const;
+ virtual int handle_input (ACE_HANDLE);
+ virtual int handle_close (ACE_HANDLE = ACE_INVALID_HANDLE,
+ ACE_Reactor_Mask = ACE_Event_Handler::ALL_EVENTS_MASK);
+ virtual int handle_timeout (const ACE_Time_Value &tv, const void *arg);
+
+ // = Really should be private...
+ virtual ~Logging_Handler (void);
+ // Ensure dynamic allocation.
+
+private:
+ char host_name_[MAXHOSTNAMELEN + 1];
+ // Host we are connected to.
+
+ ACE_SOCK_Stream cli_stream_;
+ // Connection with client
+};
+
+#endif /* _CLIENT_HANDLER_H */
diff --git a/ACE/examples/Logger/simple-server/Makefile.am b/ACE/examples/Logger/simple-server/Makefile.am
new file mode 100644
index 00000000000..a018d587b98
--- /dev/null
+++ b/ACE/examples/Logger/simple-server/Makefile.am
@@ -0,0 +1,38 @@
+## Process this file with automake to create Makefile.in
+##
+## $Id$
+##
+## This file was generated by MPC. Any changes made directly to
+## this file will be lost the next time it is generated.
+##
+## MPC Command:
+## /acebuilds/ACE_wrappers-repository/bin/mwc.pl -include /acebuilds/MPC/config -include /acebuilds/MPC/templates -feature_file /acebuilds/ACE_wrappers-repository/local.features -noreldefs -type automake -exclude build,Kokyu
+
+ACE_BUILDDIR = $(top_builddir)
+ACE_ROOT = $(top_srcdir)
+
+## Makefile.Logger_Simple_Server.am
+noinst_PROGRAMS = server_loggerd
+
+server_loggerd_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+server_loggerd_SOURCES = \
+ Logging_Acceptor.cpp \
+ Logging_Handler.cpp \
+ server_loggerd.cpp \
+ Logging_Acceptor.h \
+ Logging_Handler.h \
+ Reactor_Singleton.h
+
+server_loggerd_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Clean up template repositories, etc.
+clean-local:
+ -rm -f *~ *.bak *.rpo *.sym lib*.*_pure_* core core.*
+ -rm -f gcctemp.c gcctemp so_locations *.ics
+ -rm -rf cxx_repository ptrepository ti_files
+ -rm -rf templateregistry ir.out
+ -rm -rf ptrepository SunWS_cache Templates.DB
diff --git a/ACE/examples/Logger/simple-server/Reactor_Singleton.h b/ACE/examples/Logger/simple-server/Reactor_Singleton.h
new file mode 100644
index 00000000000..ec0653125a9
--- /dev/null
+++ b/ACE/examples/Logger/simple-server/Reactor_Singleton.h
@@ -0,0 +1,33 @@
+/* -*- C++ -*- */
+// $Id$
+
+
+// ============================================================================
+//
+// = LIBRARY
+// examples
+//
+// = FILENAME
+// Reactor_Singleton.h
+//
+// = AUTHOR
+// Doug Schmidt
+//
+// ============================================================================
+
+#ifndef _REACTOR_SINGLETON_H
+#define _REACTOR_SINGLETON_H
+
+#include "ace/Singleton.h"
+#include "ace/Null_Mutex.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/Reactor.h"
+
+// Our global Reactor Singleton.
+typedef ACE_Singleton<ACE_Reactor, ACE_Null_Mutex> REACTOR;
+
+#endif /* _REACTOR_SINGLETON_H */
diff --git a/ACE/examples/Logger/simple-server/server_loggerd.cpp b/ACE/examples/Logger/simple-server/server_loggerd.cpp
new file mode 100644
index 00000000000..f323a2f3826
--- /dev/null
+++ b/ACE/examples/Logger/simple-server/server_loggerd.cpp
@@ -0,0 +1,85 @@
+// $Id$
+
+// This server daemon collects, formats, and displays logging
+// information forwarded from client daemons running on other hosts in
+// the network.
+//
+// In addition, it also illustrates how the ACE_Reactor framework is
+// used.
+
+#include "ace/Get_Opt.h"
+#include "ace/Log_Msg.h"
+#include "ace/Signal.h"
+
+#include "Logging_Acceptor.h"
+#include "Reactor_Singleton.h"
+
+ACE_RCSID(simple_server, server_loggerd, "$Id$")
+
+static sig_atomic_t finished = 0;
+
+extern "C" void
+handler (int)
+{
+ finished = 1;
+}
+
+// It doesn't get anymore const than this....
+static const u_short PORT = ACE_DEFAULT_SERVER_PORT;
+
+int
+ACE_TMAIN (int argc, ACE_TCHAR *argv[])
+{
+ // Register a signal handler.
+ ACE_Sig_Action sa ((ACE_SignalHandler) handler, SIGINT);
+ ACE_UNUSED_ARG (sa);
+
+ Logging_Acceptor *peer_acceptor;
+ ACE_NEW_RETURN (peer_acceptor,
+ Logging_Acceptor,
+ 1);
+
+ ACE_INET_Addr addr (PORT);
+
+ ACE_Get_Opt get_opt (argc, argv, ACE_TEXT ("p:"));
+
+ for (int c; (c = get_opt ()) != -1; )
+ switch (c)
+ {
+ case 'p':
+ addr.set (ACE_OS::atoi (get_opt.opt_arg ()));
+ break;
+ default:
+ break;
+ }
+
+ if (peer_acceptor->open (addr) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("open")),
+ -1);
+ else if (REACTOR::instance ()->register_handler
+ (peer_acceptor,
+ ACE_Event_Handler::ACCEPT_MASK) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("registering service with ACE_Reactor\n")),
+ -1);
+
+ // Run forever, performing the logging service.
+
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("(%P|%t) starting up server logging daemon\n")));
+
+ while (!finished)
+ REACTOR::instance ()->handle_events ();
+
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("(%P|%t) shutting down server logging daemon\n")));
+ return 0;
+}
+
+
+#if defined (ACE_HAS_EXPLICIT_STATIC_TEMPLATE_MEMBER_INSTANTIATION)
+template ACE_Singleton<ACE_Reactor, ACE_Null_Mutex> *
+ ACE_Singleton<ACE_Reactor, ACE_Null_Mutex>::singleton_;
+#endif /* ACE_HAS_EXPLICIT_STATIC_TEMPLATE_MEMBER_INSTANTIATION */
diff --git a/ACE/examples/Makefile.am b/ACE/examples/Makefile.am
new file mode 100644
index 00000000000..1e8ba6f626f
--- /dev/null
+++ b/ACE/examples/Makefile.am
@@ -0,0 +1,43 @@
+## Process this file with automake to create Makefile.in
+##
+## $Id$
+##
+## This file was generated by MPC. Any changes made directly to
+## this file will be lost the next time it is generated.
+##
+## MPC Command:
+## /acebuilds/ACE_wrappers-repository/bin/mwc.pl -include /acebuilds/MPC/config -include /acebuilds/MPC/templates -feature_file /acebuilds/ACE_wrappers-repository/local.features -noreldefs -type automake -exclude build,Kokyu
+
+SUBDIRS = \
+ APG \
+ ASX \
+ Bounded_Packet_Relay \
+ C++NPv1 \
+ C++NPv2 \
+ Connection \
+ DLL \
+ Export \
+ IOStream \
+ IPC_SAP \
+ Log_Msg \
+ Logger \
+ Map_Manager \
+ Mem_Map \
+ Misc \
+ NT_Service \
+ Naming \
+ OS \
+ QOS \
+ Reactor \
+ Registry \
+ Service_Configurator \
+ Shared_Malloc \
+ Shared_Memory \
+ Smart_Pointers \
+ Synch \
+ System_V_IPC \
+ TMCast \
+ Threads \
+ Timer_Queue \
+ Web_Crawler
+
diff --git a/ACE/examples/Map_Manager/Makefile.am b/ACE/examples/Map_Manager/Makefile.am
new file mode 100644
index 00000000000..d5f39e68514
--- /dev/null
+++ b/ACE/examples/Map_Manager/Makefile.am
@@ -0,0 +1,33 @@
+## Process this file with automake to create Makefile.in
+##
+## $Id$
+##
+## This file was generated by MPC. Any changes made directly to
+## this file will be lost the next time it is generated.
+##
+## MPC Command:
+## /acebuilds/ACE_wrappers-repository/bin/mwc.pl -include /acebuilds/MPC/config -include /acebuilds/MPC/templates -feature_file /acebuilds/ACE_wrappers-repository/local.features -noreldefs -type automake -exclude build,Kokyu
+
+ACE_BUILDDIR = $(top_builddir)
+ACE_ROOT = $(top_srcdir)
+
+## Makefile.Map_Manager.am
+noinst_PROGRAMS = Map_Manager
+
+Map_Manager_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+Map_Manager_SOURCES = \
+ test_hash_map_manager.cpp
+
+Map_Manager_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Clean up template repositories, etc.
+clean-local:
+ -rm -f *~ *.bak *.rpo *.sym lib*.*_pure_* core core.*
+ -rm -f gcctemp.c gcctemp so_locations *.ics
+ -rm -rf cxx_repository ptrepository ti_files
+ -rm -rf templateregistry ir.out
+ -rm -rf ptrepository SunWS_cache Templates.DB
diff --git a/ACE/examples/Map_Manager/Map_Manager.mpc b/ACE/examples/Map_Manager/Map_Manager.mpc
new file mode 100644
index 00000000000..3a433cab0d4
--- /dev/null
+++ b/ACE/examples/Map_Manager/Map_Manager.mpc
@@ -0,0 +1,6 @@
+// -*- MPC -*-
+// $Id$
+
+project: aceexe {
+ exename = Map_Manager
+}
diff --git a/ACE/examples/Map_Manager/test_hash_map_manager.cpp b/ACE/examples/Map_Manager/test_hash_map_manager.cpp
new file mode 100644
index 00000000000..91e08e5c58c
--- /dev/null
+++ b/ACE/examples/Map_Manager/test_hash_map_manager.cpp
@@ -0,0 +1,80 @@
+// $Id$
+
+#include "ace/OS_main.h"
+#include "ace/Hash_Map_Manager.h"
+#include "ace/ACE.h"
+#include "ace/SString.h"
+#include "ace/Synch.h"
+#include "ace/Synch_Traits.h"
+#include "ace/OS_NS_stdio.h"
+#include "ace/os_include/os_assert.h"
+
+ACE_RCSID(Map_Manager, test_hash_map_manager, "$Id$")
+
+const int MAX_KEY_LEN = 1000;
+
+typedef ACE_Hash_Map_Manager<ACE_TString, ACE_TString, ACE_SYNCH_RW_MUTEX> MAP_MANAGER;
+
+int
+ACE_TMAIN (int argc, ACE_TCHAR *argv[])
+{
+ if (argc != 4)
+ ACE_ERROR_RETURN ((LM_ERROR, "usage: %s tablesize file1 file2\n",
+ argv[0]), -1);
+ else
+ {
+ int total = ACE_OS::atoi (argv[1]);
+
+ if (!ACE_OS::freopen (argv[2], ACE_TEXT("r"), stdin))
+ ACE_OS::perror (argv[0]), ACE_OS::exit (1);
+
+ MAP_MANAGER hash (total);
+
+ ACE_TCHAR key[MAX_KEY_LEN];
+
+ while (ACE_OS::fgets (key, sizeof key, stdin))
+ // stream ops are just too slow!!
+ {
+ ACE_TString string (key);
+ hash.bind (string, string);
+ }
+
+ fclose (stdin);
+
+ MAP_MANAGER::ITERATOR iterator (hash);
+
+ for (MAP_MANAGER::ENTRY *entry = 0;
+ iterator.next (entry) != 0;
+ iterator.advance ())
+ ACE_DEBUG ((LM_DEBUG, "%s %s\n",
+ entry->ext_id_.fast_rep (),
+ entry->int_id_.fast_rep ()));
+
+ if (!ACE_OS::freopen (argv[3], ACE_TEXT("r"), stdin))
+ ACE_OS::perror (argv[0]), exit (1);
+
+ while (ACE_OS::fgets (key, sizeof key, stdin))
+ {
+ ACE_TString name (key);
+ ACE_TString value;
+ assert (hash.find (name, value) != -1);
+ assert (name == value);
+ }
+
+ if (!ACE_OS::freopen (argv[3], ACE_TEXT("r"), stdin))
+ ACE_OS::perror (argv[0]), exit (1);
+
+ while (ACE_OS::fgets (key, sizeof key, stdin))
+ {
+ ACE_TString string (key);
+ assert (hash.unbind (string) != -1);
+ }
+
+ assert (hash.current_size () == 0);
+
+ fclose (stdin);
+ }
+
+ return 0;
+}
+
diff --git a/ACE/examples/Mem_Map/IO-tests/.cvsignore b/ACE/examples/Mem_Map/IO-tests/.cvsignore
new file mode 100644
index 00000000000..80ea1892dab
--- /dev/null
+++ b/ACE/examples/Mem_Map/IO-tests/.cvsignore
@@ -0,0 +1,2 @@
+test_io
+test_io
diff --git a/ACE/examples/Mem_Map/IO-tests/IO_Test.cpp b/ACE/examples/Mem_Map/IO-tests/IO_Test.cpp
new file mode 100644
index 00000000000..86f2596098e
--- /dev/null
+++ b/ACE/examples/Mem_Map/IO-tests/IO_Test.cpp
@@ -0,0 +1,240 @@
+// $Id$
+
+#if !defined(_WIN32)
+
+#include "ace/OS_NS_string.h"
+#include "ace/OS_NS_unistd.h"
+#include "ace/OS_NS_stdio.h"
+#include "ace/Mem_Map.h"
+#include "ace/Log_Msg.h"
+#include "IO_Test.h"
+
+ACE_RCSID(IO_tests, IO_Test, "$Id$")
+
+
+
+IO_Test::IO_Test (const char *name,
+ ACE_Profile_Timer &tm)
+ : name_ (name), tm_ (tm)
+{
+}
+
+IO_Test::~IO_Test (void)
+{
+}
+
+const char *
+IO_Test::name (void)
+{
+ return this->name_;
+}
+
+Slow_Read_Write_Test::Slow_Read_Write_Test (const char *name,
+ ACE_Profile_Timer &tm)
+ : IO_Test (name, tm)
+{
+}
+
+int
+Slow_Read_Write_Test::run_test (int iterations,
+ FILE *input_fp,
+ FILE *output_fp)
+{
+ ACE_HANDLE ifd = fileno (input_fp);
+ ACE_HANDLE ofd = fileno (output_fp);
+
+ this->tm_.start ();
+
+ while (--iterations >= 0)
+ {
+ char c;
+
+ while (ACE_OS::read (ifd, &c, sizeof c) > 0)
+ ::write (ofd, &c, sizeof c);
+
+ ACE_OS::lseek (ifd, 0, SEEK_SET);
+ ACE_OS::lseek (ofd, 0, SEEK_SET);
+ }
+
+ this->tm_.stop ();
+ return 0;
+}
+
+Stdio_Test::Stdio_Test (const char *name,
+ ACE_Profile_Timer &tm)
+ : IO_Test (name, tm)
+{
+}
+
+int
+Stdio_Test::run_test (int iterations,
+ FILE *input_fp,
+ FILE *output_fp)
+{
+ this->tm_.start ();
+
+ while (--iterations >= 0)
+ {
+ int c;
+
+ while ((c = getc (input_fp)) != EOF)
+ putc (c, output_fp);
+
+ ACE_OS::rewind (input_fp);
+ ACE_OS::rewind (output_fp);
+ }
+ this->tm_.stop ();
+ return 0;
+}
+
+Block_Read_Write_Test::Block_Read_Write_Test (const char *name,
+ ACE_Profile_Timer &tm)
+ : IO_Test (name, tm)
+{
+}
+
+int
+Block_Read_Write_Test::run_test (int iterations,
+ FILE *input_fp,
+ FILE *output_fp)
+{
+ int ifd = fileno (input_fp);
+ int ofd = fileno (output_fp);
+
+ this->tm_.start ();
+
+ while (--iterations >= 0)
+ {
+ char buf[BUFSIZ];
+ ssize_t n;
+
+ while ((n = ACE_OS::read (ifd,
+ buf,
+ sizeof buf)) > 0)
+ ::write (ofd, buf, n);
+
+ ACE_OS::lseek (ifd, 0, SEEK_SET);
+ ACE_OS::lseek (ofd, 0, SEEK_SET);
+ }
+
+ this->tm_.stop ();
+ return 0;
+}
+
+Block_Fread_Fwrite_Test::Block_Fread_Fwrite_Test (const char *name,
+ ACE_Profile_Timer &tm)
+ : IO_Test (name, tm)
+{
+}
+
+int
+Block_Fread_Fwrite_Test::run_test (int iterations,
+ FILE *input_fp,
+ FILE *output_fp)
+{
+ this->tm_.start ();
+
+ while (--iterations >= 0)
+ {
+ char buf[BUFSIZ];
+ ssize_t n;
+
+ while ((n = ACE_OS::fread (buf,
+ 1,
+ sizeof buf,
+ input_fp)) != 0)
+ ::fwrite (buf, n, 1, output_fp);
+
+ ACE_OS::rewind (input_fp);
+ ACE_OS::rewind (output_fp);
+ }
+
+ this->tm_.stop ();
+ return 0;
+}
+
+Mmap1_Test::Mmap1_Test (const char *name,
+ ACE_Profile_Timer &tm)
+ : IO_Test (name, tm)
+{
+}
+
+int
+Mmap1_Test::run_test (int iterations,
+ FILE *input_fp,
+ FILE *output_fp)
+{
+ ACE_Mem_Map map_input (fileno (input_fp));
+ void *src = map_input.addr ();
+
+ if (src == MAP_FAILED)
+ ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("%C"), this->name ()), -1);
+ else
+ {
+ this->tm_.start ();
+
+ while (--iterations >= 0)
+ {
+ if (ACE_OS::write (fileno (output_fp),
+ src,
+ map_input.size ()) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%C"),
+ this->name ()),
+ -1);
+ ACE_OS::lseek (fileno (output_fp),
+ 0,
+ SEEK_SET);
+ }
+
+ this->tm_.stop ();
+ }
+
+ if (map_input.unmap () == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%C"),
+ this->name ()),
+ -1);
+ else
+ return 0;
+}
+
+Mmap2_Test::Mmap2_Test (const char *name,
+ ACE_Profile_Timer &tm)
+ : IO_Test (name, tm)
+{
+}
+
+int
+Mmap2_Test::run_test (int iterations,
+ FILE *input_fp,
+ FILE *output_fp)
+{
+ ACE_Mem_Map map_input (fileno (input_fp));
+ int size = map_input.size ();
+ ACE_Mem_Map map_output (fileno (output_fp),
+ size,
+ PROT_WRITE,
+ MAP_SHARED);
+ void *src = map_input.addr ();
+ void *dst = map_output.addr ();
+
+ if (src == MAP_FAILED || dst == MAP_FAILED)
+ return -1;
+ else
+ {
+ this->tm_.start ();
+
+ while (--iterations >= 0)
+ ACE_OS::memcpy (dst, src, size);
+
+ this->tm_.stop ();
+ }
+
+ if (map_input.unmap () == -1
+ || map_output.unmap () == -1)
+ return -1;
+ else
+ return 0;
+}
+#endif
diff --git a/ACE/examples/Mem_Map/IO-tests/IO_Test.h b/ACE/examples/Mem_Map/IO-tests/IO_Test.h
new file mode 100644
index 00000000000..3c130b32363
--- /dev/null
+++ b/ACE/examples/Mem_Map/IO-tests/IO_Test.h
@@ -0,0 +1,100 @@
+/* -*- C++ -*- */
+// $Id$
+
+/* Class hierarchy for the File I/O tests. */
+
+#include "ace/Profile_Timer.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+/* Base class for all the File I/O tests. */
+
+class IO_Test
+{
+public:
+
+ // Initialize the test name
+ IO_Test (const char *name,
+ ACE_Profile_Timer &tm);
+
+ // Destructor.
+ virtual ~IO_Test (void);
+
+ // Return the name of the test
+ const char *name (void);
+
+ // Execute the IO test (note this is a pure virtual function...)
+ virtual int run_test (int iterations,
+ FILE *input_fp,
+ FILE *output_fp) = 0;
+
+protected:
+ // Name of the test
+ const char *name_;
+
+ // Reference to a timer
+ ACE_Profile_Timer &tm_;
+};
+
+class Slow_Read_Write_Test : public IO_Test
+{
+public:
+ Slow_Read_Write_Test (const char *name,
+ ACE_Profile_Timer &tm);
+ virtual int run_test (int iterations,
+ FILE *input_fp,
+ FILE *output_fp);
+};
+
+class Stdio_Test : public IO_Test
+{
+public:
+ Stdio_Test (const char *name,
+ ACE_Profile_Timer &tm);
+ virtual int run_test (int iterations,
+ FILE *input_fp,
+ FILE *output_fp);
+};
+
+class Block_Read_Write_Test : public IO_Test
+{
+public:
+ Block_Read_Write_Test (const char *name,
+ ACE_Profile_Timer &tm);
+ virtual int run_test (int iterations,
+ FILE *input_fp,
+ FILE *output_fp);
+};
+
+class Block_Fread_Fwrite_Test : public IO_Test
+{
+public:
+ Block_Fread_Fwrite_Test (const char *name,
+ ACE_Profile_Timer &tm);
+ virtual int run_test (int iterations,
+ FILE *input_fp,
+ FILE *output_fp);
+};
+
+class Mmap1_Test : public IO_Test
+{
+public:
+ Mmap1_Test (const char *name,
+ ACE_Profile_Timer &tm);
+ virtual int run_test (int iterations,
+ FILE *input_fp,
+ FILE *output_fp);
+};
+
+class Mmap2_Test : public IO_Test
+{
+public:
+ Mmap2_Test (const char *name,
+ ACE_Profile_Timer &tm);
+ virtual int run_test (int iterations,
+ FILE *input_fp,
+ FILE *output_fp);
+};
+
diff --git a/ACE/examples/Mem_Map/IO-tests/Makefile.am b/ACE/examples/Mem_Map/IO-tests/Makefile.am
new file mode 100644
index 00000000000..9a6e3638c29
--- /dev/null
+++ b/ACE/examples/Mem_Map/IO-tests/Makefile.am
@@ -0,0 +1,40 @@
+## Process this file with automake to create Makefile.in
+##
+## $Id$
+##
+## This file was generated by MPC. Any changes made directly to
+## this file will be lost the next time it is generated.
+##
+## MPC Command:
+## /acebuilds/ACE_wrappers-repository/bin/mwc.pl -include /acebuilds/MPC/config -include /acebuilds/MPC/templates -feature_file /acebuilds/ACE_wrappers-repository/local.features -noreldefs -type automake -exclude build,Kokyu
+
+ACE_BUILDDIR = $(top_builddir)
+ACE_ROOT = $(top_srcdir)
+
+
+## Makefile.Mem_Map_IO_Tests.am
+
+if !BUILD_ACE_FOR_TAO
+noinst_PROGRAMS = test_io
+
+test_io_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+test_io_SOURCES = \
+ IO_Test.cpp \
+ test_io.cpp \
+ IO_Test.h
+
+test_io_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+endif !BUILD_ACE_FOR_TAO
+
+## Clean up template repositories, etc.
+clean-local:
+ -rm -f *~ *.bak *.rpo *.sym lib*.*_pure_* core core.*
+ -rm -f gcctemp.c gcctemp so_locations *.ics
+ -rm -rf cxx_repository ptrepository ti_files
+ -rm -rf templateregistry ir.out
+ -rm -rf ptrepository SunWS_cache Templates.DB
diff --git a/ACE/examples/Mem_Map/IO-tests/Mem_Map_IO_Tests.mpc b/ACE/examples/Mem_Map/IO-tests/Mem_Map_IO_Tests.mpc
new file mode 100644
index 00000000000..6e2bcc9f3aa
--- /dev/null
+++ b/ACE/examples/Mem_Map/IO-tests/Mem_Map_IO_Tests.mpc
@@ -0,0 +1,6 @@
+// -*- MPC -*-
+// $Id$
+
+project : aceexe {
+ avoids += ace_for_tao
+}
diff --git a/ACE/examples/Mem_Map/IO-tests/test_io.cpp b/ACE/examples/Mem_Map/IO-tests/test_io.cpp
new file mode 100644
index 00000000000..b60401cc813
--- /dev/null
+++ b/ACE/examples/Mem_Map/IO-tests/test_io.cpp
@@ -0,0 +1,211 @@
+// $Id$
+
+// Test program for different methods of copying files.
+
+#include "ace/OS_NS_stdio.h"
+#include "ace/OS_NS_unistd.h"
+#include "ace/ACE.h"
+#include "ace/Profile_Timer.h"
+#include "ace/Get_Opt.h"
+#include "ace/Signal.h"
+#include "ace/Log_Msg.h"
+#include "IO_Test.h"
+
+ACE_RCSID(IO_tests, test_io, "$Id$")
+
+#if !defined(_WIN32)
+
+// Name of program.
+static const ACE_TCHAR *program_name;
+
+// Name of default input file.
+static const ACE_TCHAR *input_filename = ACE_TEXT ("/usr/dict/words");
+
+// Name of default output file.
+static const ACE_TCHAR *output_filename = ACE_TEXT ("/tmp/foo");
+
+// Check if removing output file upon completion...
+static int remove_output = 1;
+
+// Count of the number of iterations to run the tests.
+static int iteration_count = 100;
+
+// Profiler used to keep track of file I/O time.
+static ACE_Profile_Timer profile_timer;
+
+// Explain usage and exit.
+
+static void
+print_usage_and_die (void)
+{
+ ACE_OS::fprintf (stderr, "usage: %s"
+ " [-i input_file] [-o output_file] [-n iteration_count] [-r]\n",
+ ACE_TEXT_ALWAYS_CHAR (program_name));
+ ACE_OS::exit (1);
+}
+
+// Clean up the output file on exit from a signal.
+
+extern "C" void
+cleanup (int = 0)
+{
+ if (remove_output)
+ ACE_OS::unlink (output_filename);
+ ACE_OS::exit (0);
+}
+
+// Parse the command-line arguments and set options.
+
+static void
+parse_args (int argc, ACE_TCHAR *argv[])
+{
+ ACE_Get_Opt get_opt (argc, argv, ACE_TEXT ("i:n:o:r"));
+
+ for (int c; ((c = get_opt ()) != -1); )
+ switch (c)
+ {
+ case 'i':
+ input_filename = get_opt.opt_arg ();
+ break;
+ case 'n':
+ iteration_count = ACE_OS::atoi (get_opt.opt_arg ());
+ break;
+ case 'o':
+ output_filename = get_opt.opt_arg ();
+ break;
+ case 'r':
+ remove_output = 0;
+ break;
+ default:
+ print_usage_and_die ();
+ break;
+ }
+}
+
+// Vector of pointers to derived classes that inherit from IO_Test
+// base class.
+
+static IO_Test *test_vector[100];
+
+static int
+run_tests (int iterations, FILE *input_fp, FILE *output_fp)
+{
+ int i = 0;
+
+ ACE_NEW_RETURN (test_vector[i],
+ Stdio_Test ("Stdio_Test",
+ profile_timer),
+ -1);
+ i++;
+ ACE_NEW_RETURN (test_vector[i],
+ Block_Fread_Fwrite_Test ("Block_Fread_Fwrite_Test",
+ profile_timer),
+ -1);
+ i++;
+ ACE_NEW_RETURN (test_vector[i],
+ Block_Read_Write_Test ("Block_Read_Write_Test",
+ profile_timer),
+ -1);
+ i++;
+ ACE_NEW_RETURN (test_vector[i],
+ Mmap1_Test ("Mmap1_Test",
+ profile_timer),
+ -1);
+ i++;
+ ACE_NEW_RETURN (test_vector[i],
+ Mmap2_Test ("Mmap2_Test",
+ profile_timer),
+ -1);
+ i++;
+ ACE_NEW_RETURN (test_vector[i],
+ Slow_Read_Write_Test ("Slow_Read_Write_Test",
+ profile_timer),
+ -1);
+ i++;
+
+ test_vector[i] = (IO_Test *) 0;
+
+ for (i = 0; test_vector[i] != 0; i++)
+ {
+ ACE_HANDLE hfile = fileno (output_fp);
+ if (ACE_OS::ftruncate (hfile, 0) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%s\n"),
+ ACE_TEXT ("ftruncate")),
+ -1);
+
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("--------------------\n")
+ ACE_TEXT ("starting %C for %d iterations(s):\n"),
+ test_vector[i]->name (),
+ iterations));
+
+ test_vector[i]->run_test (iterations,
+ input_fp,
+ output_fp);
+
+ ACE_Profile_Timer::ACE_Elapsed_Time et;
+ profile_timer.elapsed_time (et);
+
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("wallclock time = %f, user time = %f, system time = %f\n"),
+ et.real_time,
+ et.user_time,
+ et.system_time));
+
+ delete test_vector[i];
+ }
+
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("--------------------\n")));
+ return 0;
+}
+
+int
+main (int argc, ACE_TCHAR *argv[])
+{
+ program_name = ACE::basename (argv[0],
+ ACE_DIRECTORY_SEPARATOR_CHAR);
+ parse_args (argc, argv);
+
+ ACE_Sig_Action sa ((ACE_SignalHandler) cleanup, SIGINT);
+ ACE_UNUSED_ARG (sa);
+
+ FILE *input_fp =
+ ACE_OS::fopen (input_filename, ACE_TEXT ("r"));
+ FILE *output_fp =
+ ACE_OS::fopen (output_filename, ACE_TEXT ("w+"));
+
+ if (input_fp == 0)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ input_filename),
+ -1);
+
+ if (output_fp == 0)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ output_filename),
+ -1);
+
+ ACE_OS::unlink (output_filename);
+
+ if (run_tests (iteration_count,
+ input_fp,
+ output_fp) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("%p\n"), ACE_TEXT ("run_tests")),
+ -1);
+
+ if (ACE_OS::fclose (input_fp) == -1
+ || ACE_OS::fclose (output_fp) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("%p\n"), ACE_TEXT ("fclose")),
+ -1);
+ cleanup ();
+ return 0;
+}
+#else
+int ACE_TMAIN (int, ACE_TCHAR*[]) {
+ // not supported on win32
+ return 0;
+}
+#endif
diff --git a/ACE/examples/Mem_Map/Makefile.am b/ACE/examples/Mem_Map/Makefile.am
new file mode 100644
index 00000000000..9d8830d2147
--- /dev/null
+++ b/ACE/examples/Mem_Map/Makefile.am
@@ -0,0 +1,14 @@
+## Process this file with automake to create Makefile.in
+##
+## $Id$
+##
+## This file was generated by MPC. Any changes made directly to
+## this file will be lost the next time it is generated.
+##
+## MPC Command:
+## /acebuilds/ACE_wrappers-repository/bin/mwc.pl -include /acebuilds/MPC/config -include /acebuilds/MPC/templates -feature_file /acebuilds/ACE_wrappers-repository/local.features -noreldefs -type automake -exclude build,Kokyu
+
+SUBDIRS = \
+ IO-tests \
+ file-reverse
+
diff --git a/ACE/examples/Mem_Map/file-reverse/.cvsignore b/ACE/examples/Mem_Map/file-reverse/.cvsignore
new file mode 100644
index 00000000000..cf791234c5e
--- /dev/null
+++ b/ACE/examples/Mem_Map/file-reverse/.cvsignore
@@ -0,0 +1 @@
+file-reverse
diff --git a/ACE/examples/Mem_Map/file-reverse/Makefile.am b/ACE/examples/Mem_Map/file-reverse/Makefile.am
new file mode 100644
index 00000000000..02a081a6c88
--- /dev/null
+++ b/ACE/examples/Mem_Map/file-reverse/Makefile.am
@@ -0,0 +1,38 @@
+## Process this file with automake to create Makefile.in
+##
+## $Id$
+##
+## This file was generated by MPC. Any changes made directly to
+## this file will be lost the next time it is generated.
+##
+## MPC Command:
+## /acebuilds/ACE_wrappers-repository/bin/mwc.pl -include /acebuilds/MPC/config -include /acebuilds/MPC/templates -feature_file /acebuilds/ACE_wrappers-repository/local.features -noreldefs -type automake -exclude build,Kokyu
+
+ACE_BUILDDIR = $(top_builddir)
+ACE_ROOT = $(top_srcdir)
+
+
+## Makefile.Mem_Map_File_Reverse.am
+
+if !BUILD_ACE_FOR_TAO
+noinst_PROGRAMS = file-reverse
+
+file_reverse_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+file_reverse_SOURCES = \
+ file-reverse.cpp
+
+file_reverse_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+endif !BUILD_ACE_FOR_TAO
+
+## Clean up template repositories, etc.
+clean-local:
+ -rm -f *~ *.bak *.rpo *.sym lib*.*_pure_* core core.*
+ -rm -f gcctemp.c gcctemp so_locations *.ics
+ -rm -rf cxx_repository ptrepository ti_files
+ -rm -rf templateregistry ir.out
+ -rm -rf ptrepository SunWS_cache Templates.DB
diff --git a/ACE/examples/Mem_Map/file-reverse/Mem_Map_File_Reverse.mpc b/ACE/examples/Mem_Map/file-reverse/Mem_Map_File_Reverse.mpc
new file mode 100644
index 00000000000..368866edb73
--- /dev/null
+++ b/ACE/examples/Mem_Map/file-reverse/Mem_Map_File_Reverse.mpc
@@ -0,0 +1,7 @@
+// -*- MPC -*-
+// $Id$
+
+project : aceexe {
+ avoids += ace_for_tao
+ exename = file-reverse
+}
diff --git a/ACE/examples/Mem_Map/file-reverse/file-reverse.cpp b/ACE/examples/Mem_Map/file-reverse/file-reverse.cpp
new file mode 100644
index 00000000000..2e64c272c12
--- /dev/null
+++ b/ACE/examples/Mem_Map/file-reverse/file-reverse.cpp
@@ -0,0 +1,59 @@
+// $Id$
+
+// Print a file in reverse by using the ACE memory mapped file
+// wrapper. It is SO easy to do compared with alternatives!
+
+#include "ace/OS_main.h"
+#include "ace/Mem_Map.h"
+#include "ace/Log_Msg.h"
+
+ACE_RCSID(file_reverse, file_reverse, "$Id$")
+
+static void
+putline (const char *s)
+{
+ while (putchar (*s++) != '\n')
+ continue;
+}
+
+static void
+print_array_in_reverse (char *array,
+ int size)
+{
+ if (size <= 0)
+ return;
+
+ size--;
+
+ if (array[size] == '\0')
+ array[size] = '\n';
+
+ while (--size >= 0)
+ if (array[size] == '\n')
+ putline (array + size + 1);
+
+ putline (array);
+}
+
+int
+ACE_TMAIN (int argc, ACE_TCHAR **argv)
+{
+ ACE_LOG_MSG->open (argv[0]);
+
+ if (argc != 2)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "usage: %n file\n"),
+ -1);
+
+ ACE_Mem_Map mmap;
+
+ if (mmap.map (argv[1], -1, O_RDWR) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%n: %p\n",
+ "mmap"),
+ -1);
+
+ print_array_in_reverse ((char *) mmap.addr (),
+ mmap.size ());
+ return 0;
+}
diff --git a/ACE/examples/Misc/.cvsignore b/ACE/examples/Misc/.cvsignore
new file mode 100644
index 00000000000..a31a7786288
--- /dev/null
+++ b/ACE/examples/Misc/.cvsignore
@@ -0,0 +1,16 @@
+test_XtReactor1
+test_XtReactor2
+test_dump
+test_dump
+test_get_opt
+test_get_opt
+test_profile_timer
+test_profile_timer
+test_read_buffer
+test_read_buffer
+test_set
+test_set
+test_sstring
+test_sstring
+test_trace
+test_trace
diff --git a/ACE/examples/Misc/Makefile.am b/ACE/examples/Misc/Makefile.am
new file mode 100644
index 00000000000..8bb0b8dc8d8
--- /dev/null
+++ b/ACE/examples/Misc/Makefile.am
@@ -0,0 +1,191 @@
+## Process this file with automake to create Makefile.in
+##
+## $Id$
+##
+## This file was generated by MPC. Any changes made directly to
+## this file will be lost the next time it is generated.
+##
+## MPC Command:
+## /acebuilds/ACE_wrappers-repository/bin/mwc.pl -include /acebuilds/MPC/config -include /acebuilds/MPC/templates -feature_file /acebuilds/ACE_wrappers-repository/local.features -noreldefs -type automake -exclude build,Kokyu
+
+ACE_BUILDDIR = $(top_builddir)
+ACE_ROOT = $(top_srcdir)
+
+
+## Makefile.Misc_Test_Dump.am
+noinst_PROGRAMS = test_dump
+
+test_dump_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+test_dump_SOURCES = \
+ test_dump.cpp \
+ test_dump.h
+
+test_dump_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Makefile.Misc_Test_Get_Opt.am
+noinst_PROGRAMS += test_get_opt
+
+test_get_opt_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+test_get_opt_SOURCES = \
+ test_get_opt.cpp \
+ test_dump.h
+
+test_get_opt_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Makefile.Misc_Test_Profile_Timer.am
+
+if !BUILD_ACE_FOR_TAO
+noinst_PROGRAMS += test_profile_timer
+
+test_profile_timer_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+test_profile_timer_SOURCES = \
+ test_profile_timer.cpp \
+ test_dump.h
+
+test_profile_timer_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+endif !BUILD_ACE_FOR_TAO
+
+## Makefile.Misc_Test_Read_Buffer.am
+noinst_PROGRAMS += test_read_buffer
+
+test_read_buffer_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+test_read_buffer_SOURCES = \
+ test_read_buffer.cpp \
+ test_dump.h
+
+test_read_buffer_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Makefile.Misc_Test_Set.am
+noinst_PROGRAMS += test_set
+
+test_set_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+test_set_SOURCES = \
+ test_set.cpp \
+ test_dump.h
+
+test_set_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Makefile.Misc_Test_Sstring.am
+noinst_PROGRAMS += test_sstring
+
+test_sstring_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+test_sstring_SOURCES = \
+ test_sstring.cpp \
+ test_dump.h
+
+test_sstring_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Makefile.Misc_Test_Trace.am
+noinst_PROGRAMS += test_trace
+
+test_trace_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+test_trace_SOURCES = \
+ test_trace.cpp \
+ test_dump.h
+
+test_trace_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Makefile.Misc_Test_XtReactor1.am
+
+if BUILD_ACE_XTREACTOR
+if BUILD_MOTIF
+if BUILD_X11
+if BUILD_XT
+
+noinst_PROGRAMS += test_XtReactor1
+
+test_XtReactor1_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR) \
+ $(ACE_X11_CPPFLAGS) \
+ $(ACE_XT_CPPFLAGS)
+
+test_XtReactor1_SOURCES = \
+ test_XtReactor1.cpp \
+ test_dump.h
+
+test_XtReactor1_LDFLAGS = \
+ $(ACE_X11_LDFLAGS) $(ACE_XT_LDFLAGS)
+
+test_XtReactor1_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE_XtReactor.la \
+ $(ACE_BUILDDIR)/ace/libACE.la \
+ -lXm \
+ $(ACE_XT_LIBS) \
+ $(ACE_X11_LIBS)
+
+endif BUILD_XT
+endif BUILD_X11
+endif BUILD_MOTIF
+endif BUILD_ACE_XTREACTOR
+
+## Makefile.Misc_Test_XtReactor2.am
+
+if BUILD_ACE_XTREACTOR
+if BUILD_MOTIF
+if BUILD_X11
+if BUILD_XT
+
+noinst_PROGRAMS += test_XtReactor2
+
+test_XtReactor2_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR) \
+ $(ACE_X11_CPPFLAGS) \
+ $(ACE_XT_CPPFLAGS)
+
+test_XtReactor2_SOURCES = \
+ test_XtReactor2.cpp \
+ test_dump.h
+
+test_XtReactor2_LDFLAGS = \
+ $(ACE_X11_LDFLAGS) $(ACE_XT_LDFLAGS)
+
+test_XtReactor2_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE_XtReactor.la \
+ $(ACE_BUILDDIR)/ace/libACE.la \
+ -lXm \
+ $(ACE_XT_LIBS) \
+ $(ACE_X11_LIBS)
+
+endif BUILD_XT
+endif BUILD_X11
+endif BUILD_MOTIF
+endif BUILD_ACE_XTREACTOR
+
+## Clean up template repositories, etc.
+clean-local:
+ -rm -f *~ *.bak *.rpo *.sym lib*.*_pure_* core core.*
+ -rm -f gcctemp.c gcctemp so_locations *.ics
+ -rm -rf cxx_repository ptrepository ti_files
+ -rm -rf templateregistry ir.out
+ -rm -rf ptrepository SunWS_cache Templates.DB
diff --git a/ACE/examples/Misc/Misc.mpc b/ACE/examples/Misc/Misc.mpc
new file mode 100644
index 00000000000..b0ed858efbd
--- /dev/null
+++ b/ACE/examples/Misc/Misc.mpc
@@ -0,0 +1,66 @@
+// -*- MPC -*-
+// $Id$
+
+project(*test_dump) : aceexe {
+ exename = test_dump
+ Source_Files {
+ test_dump.cpp
+ }
+}
+
+project(*test_get_opt) : aceexe {
+ exename = test_get_opt
+ Source_Files {
+ test_get_opt.cpp
+ }
+}
+
+project(*test_profile_timer) : aceexe {
+ avoids += ace_for_tao
+ exename = test_profile_timer
+ Source_Files {
+ test_profile_timer.cpp
+ }
+}
+
+project(*test_read_buffer) : aceexe {
+ exename = test_read_buffer
+ Source_Files {
+ test_read_buffer.cpp
+ }
+}
+
+project(*test_set) : aceexe {
+ exename = test_set
+ Source_Files {
+ test_set.cpp
+ }
+}
+
+project(*test_sstring) : aceexe {
+ exename = test_sstring
+ Source_Files {
+ test_sstring.cpp
+ }
+}
+
+project(*test_trace) : aceexe {
+ exename = test_trace
+ Source_Files {
+ test_trace.cpp
+ }
+}
+
+project(*test_XtReactor1) : aceexe, ace_xtreactor, ace_motif {
+ exename = test_XtReactor1
+ Source_Files {
+ test_XtReactor1.cpp
+ }
+}
+
+project(*test_XtReactor2) : aceexe, ace_xtreactor, ace_motif {
+ exename = test_XtReactor2
+ Source_Files {
+ test_XtReactor2.cpp
+ }
+}
diff --git a/ACE/examples/Misc/test_XtReactor1.cpp b/ACE/examples/Misc/test_XtReactor1.cpp
new file mode 100644
index 00000000000..f4bef54aeae
--- /dev/null
+++ b/ACE/examples/Misc/test_XtReactor1.cpp
@@ -0,0 +1,173 @@
+// $Id$
+
+// The following is another test that exercises the Eric C. Newton's
+// <ecn@clark.net> XtReactor implementation.
+
+#include "ace/OS_main.h"
+#include "ace/XtReactor.h"
+#include "ace/Reactor.h"
+#include "ace/Message_Block.h"
+#include "ace/Log_Msg.h"
+#include "ace/OS_NS_unistd.h"
+#include "ace/OS_NS_fcntl.h"
+
+ACE_RCSID (Misc,
+ test_XtReactor1,
+ "$Id$")
+
+//#define String XtString
+#include <Xm/PushB.h>
+
+class Stdout : public ACE_Event_Handler
+{
+public:
+ Stdout (ACE_Reactor * r)
+ : reactor_ (r),
+ msg_ (1000000) // Make a very big message block.
+ {
+ int flags = ACE_OS::fcntl (ACE_STDOUT, F_GETFL);
+
+ if (flags != -1
+ && ACE_OS::fcntl (ACE_STDOUT,
+ F_SETFL, flags | O_NONBLOCK) != -1)
+ return;
+ else
+ ACE_DEBUG ((LM_DEBUG,
+ "Unable to set stdout to non-block."));
+ }
+
+ ACE_HANDLE get_handle (void) const { return ACE_STDOUT; }
+
+ int handle_output (ACE_HANDLE)
+ {
+ char *s = msg_.rd_ptr ();
+
+ if (ACE_OS::write (ACE_STDOUT, s, 1) == 1)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ "wrote output '%d'\n",
+ (int) *s));
+ msg_.rd_ptr (1);
+ }
+
+ if (msg_.length () == 0)
+ {
+ reactor_->remove_handler (this,
+ ACE_Event_Handler::WRITE_MASK);
+ msg_.rd_ptr (msg_.base ());
+ msg_.wr_ptr (msg_.base ());
+ }
+ return 0;
+ }
+
+ void put (char c)
+ {
+ if (msg_.length () == 0)
+ reactor_->register_handler (this,
+ ACE_Event_Handler::WRITE_MASK);
+
+ if (msg_.wr_ptr () < msg_.end ())
+ {
+ *msg_.wr_ptr () = c;
+ msg_.wr_ptr (1);
+ }
+ else
+ ACE_DEBUG ((LM_DEBUG,
+ "Oops... data falling off the end of the buffer!\n"));
+ }
+
+private:
+ ACE_Reactor *reactor_;
+ ACE_Message_Block msg_;
+};
+
+class Stdin : public ACE_Event_Handler
+{
+public:
+ Stdin (Stdout *out)
+ : out_ (out) {}
+
+ ACE_HANDLE get_handle () const { return ACE_STDIN; }
+
+ int handle_input (ACE_HANDLE)
+ {
+ char c;
+
+ if (ACE_OS::read (ACE_STDIN, &c, 1) == 1)
+ out_->put (c);
+
+ return 0;
+ }
+
+ int handle_timeout (const ACE_Time_Value &tv, const void *)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ "Timeout! %f\n",
+ (double) (tv.msec () / 1000.)));
+ return 0;
+ }
+
+private:
+ Stdout *out_;
+};
+
+static void
+ActivateCB (Widget, XtPointer, XtPointer)
+{
+ ACE_DEBUG ((LM_DEBUG,
+ "Button pushed!\n"));
+}
+
+int
+ACE_TMAIN (int argc, ACE_TCHAR**argv)
+{
+ // The worlds most useless user interface
+ Widget top_level = XtVaAppInitialize (NULL,
+ "buttontest",
+ NULL,
+ 0,
+ &argc,
+ argv,
+ NULL,
+ NULL);
+ char change[] = "change"; // XmCreatePushButton() wants a non-const
+ // string.
+ Widget button = XmCreatePushButton (top_level,
+ change,
+ 0,
+ 0);
+ XtManageChild (button);
+ XtAddCallback (button,
+ XmNactivateCallback,
+ ActivateCB,
+ NULL);
+
+ // A reactor beastie.
+ ACE_XtReactor xreactor (XtWidgetToApplicationContext (top_level));
+ ACE_Reactor reactor (&xreactor);
+
+ // Print a message when data is recv'd on stdin...
+ ACE_Event_Handler *stdin_;
+ ACE_NEW_RETURN (stdin_,
+ Stdin (new Stdout (&reactor)),
+ -1);
+ reactor.register_handler (stdin_,
+ ACE_Event_Handler::READ_MASK);
+
+ // Print a message every 10 seconds.
+ if (reactor.schedule_timer (stdin_, 0,
+ ACE_Time_Value (10),
+ ACE_Time_Value (10)) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%p\n",
+ "schedule_timer"),
+ -1);
+
+ // Show the top_level widget.
+ XtRealizeWidget (top_level);
+
+ // Demonstrate Reactor/Xt event loop unification.
+ XtAppMainLoop (XtWidgetToApplicationContext (top_level));
+
+ return 0;
+}
diff --git a/ACE/examples/Misc/test_XtReactor2.cpp b/ACE/examples/Misc/test_XtReactor2.cpp
new file mode 100644
index 00000000000..2e2f4be0ba2
--- /dev/null
+++ b/ACE/examples/Misc/test_XtReactor2.cpp
@@ -0,0 +1,101 @@
+// $Id$
+
+// The following test exercises the Eric C. Newton's <ecn@clark.net>
+// XtReactor implementation.
+
+#include "ace/OS_main.h"
+#include "ace/XtReactor.h"
+#include "ace/Reactor.h"
+#include "ace/Message_Block.h"
+#include "ace/Log_Msg.h"
+#include "ace/OS_NS_unistd.h"
+
+ACE_RCSID (Misc,
+ test_XtReactor2,
+ "$Id$")
+
+
+#include <Xm/PushB.h>
+
+class Stdin : public ACE_Event_Handler
+{
+public:
+ ACE_HANDLE get_handle (void) const { return ACE_STDIN; }
+
+ int handle_input (ACE_HANDLE)
+ {
+ char c;
+ if (ACE_OS::read (ACE_STDIN, &c, 1)==1)
+ ACE_DEBUG ((LM_DEBUG,
+ "Got input '%d'\n",
+ (int) c));
+ return 0;
+ }
+
+ int handle_timeout (const ACE_Time_Value &tv,
+ const void *)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ "Timeout! %f\n",
+ (double) (tv.msec ()/1000.)));
+ return 0;
+ }
+};
+
+static void
+ActivateCB (Widget, XtPointer, XtPointer)
+{
+ ACE_DEBUG ((LM_DEBUG,
+ "Button pushed!\n"));
+}
+
+int
+ACE_TMAIN (int argc, ACE_TCHAR**argv)
+{
+ // The worlds most useless user interface
+ Widget top_level = XtVaAppInitialize (NULL,
+ "buttontest",
+ NULL,
+ 0,
+ &argc,
+ argv,
+ NULL,
+ NULL);
+ char change[] = "change"; // XmCreatePushButton() wants a non-const
+ // string.
+ Widget button = XmCreatePushButton (top_level,
+ change,
+ 0,
+ 0);
+ XtManageChild (button);
+ XtAddCallback (button,
+ XmNactivateCallback,
+ ActivateCB,
+ NULL);
+
+ // A reactor beastie.
+ ACE_XtReactor xreactor (XtWidgetToApplicationContext (top_level));
+ ACE_Reactor reactor (&xreactor);
+
+ // Print a message when data is recv'd on stdin...
+ ACE_Event_Handler * stdin_;
+ ACE_NEW_RETURN (stdin_,
+ Stdin,
+ -1);
+ reactor.register_handler (stdin_,
+ ACE_Event_Handler::READ_MASK);
+
+ // Print a message every 10 seconds
+ if (reactor.schedule_timer (stdin_, 0,
+ ACE_Time_Value (10),
+ ACE_Time_Value (10)) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%p\n",
+ "schedule_timer"), -1);
+
+ // Show the top_level widget
+ XtRealizeWidget (top_level);
+
+ // Demonstrate Reactor/Xt event loop unification:
+ XtAppMainLoop (XtWidgetToApplicationContext (top_level));
+}
diff --git a/ACE/examples/Misc/test_dump.cpp b/ACE/examples/Misc/test_dump.cpp
new file mode 100644
index 00000000000..bbffe66a2bf
--- /dev/null
+++ b/ACE/examples/Misc/test_dump.cpp
@@ -0,0 +1,33 @@
+// $Id$
+
+// The following code illustrates how the ACE_Dumpable mechanisms are
+// integrated into ACE components like the SOCK_Acceptor and
+// SOCK_Stream.
+
+#include "ace/OS_main.h"
+#include "ace/Dump.h"
+#include "test_dump.h"
+
+#include "ace/Reactor.h"
+
+ACE_RCSID(Misc, test_dump, "$Id$")
+
+int
+ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ SOCK outer_sock;
+ // Note that the SOCK superclass is *not* printed.
+ SOCK_Stream outer_stream;
+ SOCK_Acceptor outer_acceptor;
+ ACE_ODB::instance ()->dump_objects ();
+ {
+ SOCK inner_sock;
+ // Note that the SOCK superclass is *not* printed.
+ SOCK_Stream inner_stream;
+ SOCK_Acceptor inner_acceptor;
+ ACE_ODB::instance ()->dump_objects ();
+ }
+ ACE_ODB::instance ()->dump_objects ();
+ return 0;
+}
+
diff --git a/ACE/examples/Misc/test_dump.h b/ACE/examples/Misc/test_dump.h
new file mode 100644
index 00000000000..9c7e0bb7de8
--- /dev/null
+++ b/ACE/examples/Misc/test_dump.h
@@ -0,0 +1,50 @@
+// $Id$
+
+// Define the classes used with templates in test_dump.cpp
+
+#ifndef __TEST_DUMP_H
+#define __TEST_DUMP_H
+
+#include "ace/Dump.h"
+#include "ace/OS_NS_stdio.h"
+
+class SOCK
+{
+public:
+ SOCK (void) { ACE_REGISTER_OBJECT (SOCK); }
+ ~SOCK (void) { ACE_REMOVE_OBJECT; }
+
+ void dump (void) const {
+ ACE_OS::fprintf (stderr, "hello from SOCK = %lu\n", (u_long) this);
+ }
+
+ // ...
+};
+
+class SOCK_Acceptor : public SOCK
+{
+public:
+ SOCK_Acceptor (void) { ACE_REGISTER_OBJECT (SOCK_Acceptor); }
+ ~SOCK_Acceptor (void) { ACE_REMOVE_OBJECT; }
+
+ void dump (void) const {
+ ACE_OS::fprintf (stderr, "hello from SOCK_Acceptor = %lu\n", (u_long) this);
+ }
+
+ // ...
+};
+
+class SOCK_Stream : public SOCK
+{
+public:
+ SOCK_Stream (void) { ACE_REGISTER_OBJECT (SOCK_Stream); }
+ ~SOCK_Stream (void) { ACE_REMOVE_OBJECT; }
+
+ void dump (void) const {
+ ACE_OS::fprintf (stderr, "hello from SOCK_Stream = %lu\n", (u_long) this);
+ }
+
+ // ...
+};
+
+#endif /* __TEST_DUMP_H */
diff --git a/ACE/examples/Misc/test_get_opt.cpp b/ACE/examples/Misc/test_get_opt.cpp
new file mode 100644
index 00000000000..3fd0a16ac80
--- /dev/null
+++ b/ACE/examples/Misc/test_get_opt.cpp
@@ -0,0 +1,54 @@
+// $Id$
+
+// Test the ACE_Get_Opt class.
+
+#include "ace/OS_main.h"
+#include "ace/Get_Opt.h"
+#include "ace/Log_Msg.h"
+
+ACE_RCSID(Misc, test_get_opt, "$Id$")
+
+int
+ACE_TMAIN (int argc, ACE_TCHAR *argv[])
+{
+ ACE_Get_Opt get_opt (argc, argv, ACE_TEXT("ab:cd:ef:gh:"));
+ int c;
+
+ while ((c = get_opt ()) != EOF)
+ switch (c)
+ {
+ case 'a':
+ ACE_DEBUG ((LM_DEBUG, "got a\n"));
+ break;
+ case 'b':
+ ACE_DEBUG ((LM_DEBUG, "got b with arg %s\n", get_opt.opt_arg ()));
+ break;
+ case 'c':
+ ACE_DEBUG ((LM_DEBUG, "got c\n"));
+ break;
+ case 'd':
+ ACE_DEBUG ((LM_DEBUG, "got d with arg %s\n", get_opt.opt_arg ()));
+ break;
+ case 'e':
+ ACE_DEBUG ((LM_DEBUG, "got e\n"));
+ break;
+ case 'f':
+ ACE_DEBUG ((LM_DEBUG, "got f with arg %s\n", get_opt.opt_arg ()));
+ break;
+ case 'g':
+ ACE_DEBUG ((LM_DEBUG, "got g\n"));
+ break;
+ case 'h':
+ ACE_DEBUG ((LM_DEBUG, "got h with arg %s\n", get_opt.opt_arg ()));
+ break;
+ default:
+ ACE_DEBUG ((LM_DEBUG, "got %c, which is unrecognized!\n", c));
+ break;
+ }
+
+ for (int i = get_opt.opt_ind (); i < argc; i++)
+ ACE_DEBUG ((LM_DEBUG, "optind = %d, argv[optind] = %s\n",
+ i, argv[i]));
+
+ return 0;
+}
diff --git a/ACE/examples/Misc/test_profile_timer.cpp b/ACE/examples/Misc/test_profile_timer.cpp
new file mode 100644
index 00000000000..adb6f599f83
--- /dev/null
+++ b/ACE/examples/Misc/test_profile_timer.cpp
@@ -0,0 +1,38 @@
+// $Id$
+
+#include "ace/OS_main.h"
+#include "ace/Profile_Timer.h"
+#include "ace/Log_Msg.h"
+#include "ace/OS_NS_stdlib.h"
+#include "ace/OS_NS_unistd.h"
+
+ACE_RCSID(Misc, test_profile_timer, "$Id$")
+
+static const int DEFAULT_ITERATIONS = 100000000;
+
+int
+ACE_TMAIN (int argc, ACE_TCHAR *argv[])
+{
+ ACE_Profile_Timer timer;
+ int iterations = argc > 1 ? ACE_OS::atoi (argv[1]) : DEFAULT_ITERATIONS;
+
+ timer.start ();
+
+ for (int i = 0; i < iterations; i++)
+ ACE_OS::getpid ();
+
+ timer.stop ();
+
+ ACE_Profile_Timer::ACE_Elapsed_Time et;
+
+ timer.elapsed_time (et);
+
+ ACE_DEBUG ((LM_DEBUG, "iterations = %d\n", iterations));
+ ACE_DEBUG ((LM_DEBUG, "real time = %f secs, user time = %f secs, system time = %f secs\n",
+ et.real_time, et.user_time, et.system_time));
+
+ ACE_DEBUG ((LM_DEBUG, "time per call = %f usecs\n",
+ (et.real_time / double (iterations)) * 1000000));
+ return 0;
+}
+
diff --git a/ACE/examples/Misc/test_read_buffer.cpp b/ACE/examples/Misc/test_read_buffer.cpp
new file mode 100644
index 00000000000..1c24aec98b7
--- /dev/null
+++ b/ACE/examples/Misc/test_read_buffer.cpp
@@ -0,0 +1,34 @@
+// $Id$
+
+#include "ace/OS_main.h"
+#include "ace/OS_NS_fcntl.h"
+#include "ace/OS_NS_unistd.h"
+#include "ace/Malloc_Base.h"
+#include "ace/Service_Config.h"
+#include "ace/Read_Buffer.h"
+#include "ace/OS_NS_stdlib.h"
+
+
+ACE_RCSID (Misc,
+ test_read_buffer,
+ "$Id$")
+
+int
+ACE_TMAIN (int argc, ACE_TCHAR *argv[])
+{
+ ACE_HANDLE handle = argc > 1 ? ACE_OS::open (argv[1], O_RDONLY) : ACE_STDIN;
+ int term = argc > 2 ? ACE_OS::atoi (argv[2]) : EOF;
+ int search = argc > 3 ? ACE_OS::atoi (argv[3]) : '\n';
+ int replace = argc > 4 ? ACE_OS::atoi (argv[4]) : '\0';
+
+ ACE_Read_Buffer rb (handle);
+
+ char *buf;
+
+ while ((buf = rb.read (term, search, replace)) != 0)
+ {
+ ACE_OS::write (ACE_STDOUT, buf, rb.size ());
+ ACE_Allocator::instance ()->free (buf);
+ }
+ return 0;
+}
diff --git a/ACE/examples/Misc/test_set.cpp b/ACE/examples/Misc/test_set.cpp
new file mode 100644
index 00000000000..4b60d3b4b11
--- /dev/null
+++ b/ACE/examples/Misc/test_set.cpp
@@ -0,0 +1,57 @@
+// $Id$
+
+#include "ace/OS_main.h"
+#include "ace/Containers.h"
+#include "ace/Log_Msg.h"
+
+int
+ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ ACE_Unbounded_Set<int> s1;
+
+ ACE_ASSERT (s1.size () == 0);
+ s1.insert_tail (10);
+ s1.insert_tail (20);
+ ACE_ASSERT (s1.size () == 2);
+
+ ACE_Unbounded_Set<int> s2 (s1);
+ ACE_ASSERT (s2.size () == 2);
+
+ ACE_Unbounded_Set<int> s3;
+ ACE_ASSERT (s3.size () == 0);
+
+ s3 = s2;
+ ACE_ASSERT (s3.size () == s2.size ());
+
+ ACE_Unbounded_Set<int> s4 (s3);
+ ACE_ASSERT (s4.size () == 2);
+
+ int *ip = 0;
+
+ ACE_DEBUG ((LM_DEBUG, "dumping s1\n"));
+ for (ACE_Unbounded_Set_Iterator<int> iter1 (s1);
+ iter1.next (ip) != 0;
+ iter1.advance ())
+ ACE_DEBUG ((LM_DEBUG, "item = %d\n", *ip));
+
+ ACE_DEBUG ((LM_DEBUG, "dumping s2\n"));
+ for (ACE_Unbounded_Set_Iterator<int> iter2 (s2);
+ iter2.next (ip) != 0;
+ iter2.advance ())
+ ACE_DEBUG ((LM_DEBUG, "item = %d\n", *ip));
+
+ ACE_DEBUG ((LM_DEBUG, "dumping s3\n"));
+ for (ACE_Unbounded_Set_Iterator<int> iter3 (s3);
+ iter3.next (ip) != 0;
+ iter3.advance ())
+ ACE_DEBUG ((LM_DEBUG, "item = %d\n", *ip));
+
+ ACE_DEBUG ((LM_DEBUG, "dumping s4\n"));
+ for (ACE_Unbounded_Set_Iterator<int> iter4 (s4);
+ iter4.next (ip) != 0;
+ iter4.advance ())
+ ACE_DEBUG ((LM_DEBUG, "item = %d\n", *ip));
+
+ return 0;
+}
+
diff --git a/ACE/examples/Misc/test_sstring.cpp b/ACE/examples/Misc/test_sstring.cpp
new file mode 100644
index 00000000000..75cfe8e1158
--- /dev/null
+++ b/ACE/examples/Misc/test_sstring.cpp
@@ -0,0 +1,26 @@
+// $Id$
+
+#include "ace/OS_main.h"
+#include "ace/SString.h"
+#include "ace/Log_Msg.h"
+
+ACE_RCSID(Misc, test_sstring, "$Id$")
+
+int
+ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ ACE_CString s1 ("hello");
+ ACE_CString s2 ("world");
+ ACE_CString s3 ("el");
+ ACE_NS_WString s4 ("hello");
+ ACE_NS_WString s5 ("world");
+ ACE_NS_WString s6 ("el");
+
+ ACE_ASSERT (s1 != s2);
+ ACE_ASSERT (s1.strstr (s2) == ACE_CString::npos);
+ ACE_ASSERT (s1.strstr (s2) == ACE_CString::npos);
+ ACE_ASSERT (s1.strstr (s3));
+ ACE_ASSERT (s4.strstr (s5) == ACE_NS_WString::npos);
+ ACE_ASSERT (s5.strstr (s6));
+ return 0;
+}
diff --git a/ACE/examples/Misc/test_trace.cpp b/ACE/examples/Misc/test_trace.cpp
new file mode 100644
index 00000000000..c400d94ec7f
--- /dev/null
+++ b/ACE/examples/Misc/test_trace.cpp
@@ -0,0 +1,114 @@
+// $Id$
+
+// ============================================================================
+//
+// = LIBRARY
+// examples/Misc
+//
+// = FILENAME
+// test_trace.cpp
+//
+// = DESCRIPTION
+// This example illustrates how to use the ACE tracing feature and
+// the ACE_TRACE macro. It also shows the use of the ACE_Task_Base
+// class running as an "active object".
+//
+// = AUTHOR
+// Douglas C. Schmidt <schmidt@cs.wustl.edu> and
+// Irfan Pyarali <irfan@cs.wustl.edu>
+//
+// ============================================================================
+
+// Enable tracing
+#define ACE_NTRACE 0
+
+#include "ace/OS_main.h"
+#include "ace/Signal.h"
+#include "ace/Task.h"
+
+ACE_RCSID(Misc, test_trace, "$Id$")
+
+class My_Task : public ACE_Task_Base
+{
+public:
+ My_Task (size_t depth)
+ : depth_ (depth)
+ {
+ }
+
+ int recursive (size_t depth);
+
+ virtual int svc (void)
+ {
+ return this->recursive (this->depth_);
+ }
+
+private:
+ size_t depth_;
+ // Depth of the recursion.
+};
+
+int
+My_Task::recursive (size_t depth)
+{
+ ACE_TRACE ("My_Task::recursive");
+
+ if (depth > 0)
+ return recursive (depth - 1);
+ else
+ return 0;
+ // Destructor of <ACE_Trace> automatically called.
+}
+
+extern "C"
+void
+exithook (void)
+{
+ ACE_TRACE ("void exithook (void)");
+
+ ACE_DEBUG ((LM_DEBUG,
+ "we're outta here!\n"));
+}
+
+int
+ACE_TMAIN (int argc, ACE_TCHAR *argv[])
+{
+ const size_t MAX_DEPTH = argc == 1 ? 10 : ACE_OS::atoi (argv[1]);
+
+ ACE_OS::atexit (exithook);
+
+ if (argc > 2)
+ ACE_Trace::set_nesting_indent (ACE_OS::atoi (argv[2]));
+
+ ACE_TRACE ("int ACE_TMAIN (int argc, ACE_TCHAR *argv[])");
+
+ ACE_Sig_Action sig1 ((ACE_SignalHandler) ACE_Trace::start_tracing,
+ SIGUSR1);
+ ACE_UNUSED_ARG (sig1);
+ ACE_Sig_Action sig2 ((ACE_SignalHandler) ACE_Trace::stop_tracing,
+ SIGUSR2);
+ ACE_UNUSED_ARG (sig2);
+
+ My_Task task (MAX_DEPTH);
+
+#if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0)
+ int n_threads = argc > 3 ? ACE_OS::atoi (argv[3]) : 4;
+
+ if (task.activate (THR_BOUND | THR_DETACHED, n_threads) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%p\n",
+ "activate"),
+ -1);
+
+ // Wait for all the threads to exit.
+ ACE_Thread_Manager::instance ()->wait ();
+#else
+ const int MAX_ITERATIONS = argc > 3 ? ACE_OS::atoi (argv[3]) : 10;
+
+ for (int i = 0; i < MAX_ITERATIONS; i++)
+ task.svc ();
+#endif /* ACE_MT_SAFE */
+
+ // Destructor automatically called.
+ return 0;
+}
diff --git a/ACE/examples/NT_Service/Makefile.am b/ACE/examples/NT_Service/Makefile.am
new file mode 100644
index 00000000000..fbc93c45f6d
--- /dev/null
+++ b/ACE/examples/NT_Service/Makefile.am
@@ -0,0 +1,44 @@
+## Process this file with automake to create Makefile.in
+##
+## $Id$
+##
+## This file was generated by MPC. Any changes made directly to
+## this file will be lost the next time it is generated.
+##
+## MPC Command:
+## /acebuilds/ACE_wrappers-repository/bin/mwc.pl -include /acebuilds/MPC/config -include /acebuilds/MPC/templates -feature_file /acebuilds/ACE_wrappers-repository/local.features -noreldefs -type automake -exclude build,Kokyu
+
+ACE_BUILDDIR = $(top_builddir)
+ACE_ROOT = $(top_srcdir)
+
+
+## Makefile.NT_Service.am
+
+if BUILD_WINREGISTRY
+if !BUILD_ACE_FOR_TAO
+if !BUILD_WINCE
+noinst_PROGRAMS = main
+
+main_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+main_SOURCES = \
+ main.cpp \
+ ntsvc.cpp \
+ ntsvc.h
+
+main_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+endif !BUILD_WINCE
+endif !BUILD_ACE_FOR_TAO
+endif BUILD_WINREGISTRY
+
+## Clean up template repositories, etc.
+clean-local:
+ -rm -f *~ *.bak *.rpo *.sym lib*.*_pure_* core core.*
+ -rm -f gcctemp.c gcctemp so_locations *.ics
+ -rm -rf cxx_repository ptrepository ti_files
+ -rm -rf templateregistry ir.out
+ -rm -rf ptrepository SunWS_cache Templates.DB
diff --git a/ACE/examples/NT_Service/NT_Service.mpc b/ACE/examples/NT_Service/NT_Service.mpc
new file mode 100644
index 00000000000..4fdbe054dfe
--- /dev/null
+++ b/ACE/examples/NT_Service/NT_Service.mpc
@@ -0,0 +1,7 @@
+// -*- MPC -*-
+// $Id$
+
+project : aceexe, winregistry {
+ avoids += wince
+ exename = main
+}
diff --git a/ACE/examples/NT_Service/README b/ACE/examples/NT_Service/README
new file mode 100644
index 00000000000..a1d4175e126
--- /dev/null
+++ b/ACE/examples/NT_Service/README
@@ -0,0 +1,45 @@
+$Id$
+
+How to use the NT_Service example.
+
+The NT_Service program has the following usage: -in -r -s -k -tn -d
+ -i: Install this program as an NT service, with specified startup
+ -r: Remove this program from the Service Manager
+ -s: Start the service
+ -k: Kill the service
+ -t: Set startup for an existing service
+ -d: Debug; run as a regular application
+
+In order to see different stages of an NT service application,
+you have to run the program several times, with different options.
+Please note: run with only one option at a time.
+
+1. Make executable NT_Service.
+
+2. First, you must initialize the service in the NT SCM database.
+ Run NT_Service with -in, where n is one of the following startup options:
+
+ //
+ // Start Type (from WinNT.h)
+ //
+ #define SERVICE_SYSTEM_START 0x00000001
+ #define SERVICE_AUTO_START 0x00000002
+ #define SERVICE_DEMAND_START 0x00000003
+ #define SERVICE_DISABLED 0x00000004
+
+ If only -i is specified, SERVICE_AUTO_START is default option.
+
+3. Now you are ready to run the actual service. Run NT_Service again,
+ this time with -s option. If the service starts successfully, it will
+ ring the system bell every second or so until the service is stopped.
+
+4. To stop service execution, run NT_Service with the -k option.
+
+5. To remove the service from the Service Control Manager database, run
+ NT_Service with -r.
+
+In addition, once you have initialized this service (by using the -i option)
+you can change its startup type to one of the other values above. To do
+this, run NT_Service with -tn option. n is as explained above for -i.
+
+In order to debug the service's execution itself, use the -d option.
diff --git a/ACE/examples/NT_Service/main.cpp b/ACE/examples/NT_Service/main.cpp
new file mode 100644
index 00000000000..fbbf4a60cf4
--- /dev/null
+++ b/ACE/examples/NT_Service/main.cpp
@@ -0,0 +1,256 @@
+// $Id$
+
+// ============================================================================
+//
+// = LIBRARY
+// examples/NT_Service
+//
+// = FILENAME
+// main.cpp
+//
+// = DESCRIPTION
+// This is the main program - it just hands control off to the
+// process instance to figure out what to do. This program only
+// runs on Win32.
+//
+// = AUTHOR
+// Gonzalo Diethelm <gonzo@cs.wustl.edu>
+// and Steve Huston <shuston@riverace.com>
+//
+// ============================================================================
+
+#include "ace/Get_Opt.h"
+#include "ntsvc.h"
+// FUZZ: disable check_for_streams_include
+#include "ace/streams.h"
+#include "ace/OS_NS_errno.h"
+
+// Default for the -i (install) option
+#define DEFAULT_SERVICE_INIT_STARTUP SERVICE_AUTO_START
+
+class Process
+{
+public:
+ Process (void);
+ ~Process (void);
+
+ int run(int argc, ACE_TCHAR* argv[]);
+
+private:
+ void parse_args (int argc,
+ ACE_TCHAR* argv[]);
+ void print_usage_and_die (void);
+
+private:
+ char progname[128];
+
+ int opt_install;
+ int opt_remove;
+ int opt_start;
+ int opt_kill;
+ int opt_type;
+ int opt_debug;
+
+ int opt_startup;
+};
+
+typedef ACE_Singleton<Process, ACE_Mutex> PROCESS;
+
+Process::Process (void)
+ : opt_install (0),
+ opt_remove (0),
+ opt_start (0),
+ opt_kill (0),
+ opt_type (0),
+ opt_debug (0),
+ opt_startup (0)
+{
+ ACE_OS::strcpy (progname,
+ "service");
+ ACE::init ();
+}
+
+Process::~Process (void)
+{
+ ACE::fini ();
+}
+
+void
+Process::print_usage_and_die (void)
+{
+ ACE_DEBUG ((LM_INFO,
+ "Usage: %s"
+ " -in -r -s -k -tn -d\n"
+ " -i: Install this program as an NT service, with specified startup\n"
+ " -r: Remove this program from the Service Manager\n"
+ " -s: Start the service\n"
+ " -k: Kill the service\n"
+ " -t: Set startup for an existing service\n"
+ " -d: Debug; run as a regular application\n",
+ progname,
+ 0));
+ ACE_OS::exit(1);
+}
+
+void
+Process::parse_args (int argc, ACE_TCHAR* argv[])
+{
+ ACE_Get_Opt get_opt (argc, argv, ACE_TEXT ("i:rskt:d"));
+ int c;
+
+ while ((c = get_opt ()) != -1)
+ switch (c)
+ {
+ case 'i':
+ opt_install = 1;
+ opt_startup = ACE_OS::atoi (get_opt.opt_arg ());
+ if (opt_startup <= 0)
+ print_usage_and_die ();
+ break;
+ case 'r':
+ opt_remove = 1;
+ break;
+ case 's':
+ opt_start = 1;
+ break;
+ case 'k':
+ opt_kill = 1;
+ break;
+ case 't':
+ opt_type = 1;
+ opt_startup = ACE_OS::atoi (get_opt.opt_arg ());
+ if (opt_startup <= 0)
+ print_usage_and_die ();
+ break;
+ case 'd':
+ opt_debug = 1;
+ break;
+ default:
+ // -i can also be given without a value - if so, it defaults
+ // to defined value.
+ if (ACE_OS::strcmp (get_opt.argv ()[get_opt.opt_ind () - 1], ACE_TEXT ("-i")) == 0)
+ {
+ opt_install = 1;
+ opt_startup = DEFAULT_SERVICE_INIT_STARTUP;
+ }
+ else
+ {
+ print_usage_and_die ();
+ }
+ break;
+ }
+}
+
+// Define a function to handle Ctrl+C to cleanly shut this down.
+
+static BOOL __stdcall
+ConsoleHandler (DWORD ctrlType)
+{
+ ACE_UNUSED_ARG (ctrlType);
+ SERVICE::instance ()->handle_control (SERVICE_CONTROL_STOP);
+ return TRUE;
+}
+
+ACE_NT_SERVICE_DEFINE (Beeper,
+ Service,
+ ACE_TEXT ("Annoying Beeper Service"));
+
+int
+Process::run (int argc, ACE_TCHAR* argv[])
+{
+ SERVICE::instance ()->name (ACE_TEXT ("Beeper"),
+ ACE_TEXT ("Annoying Beeper Service"));
+
+ parse_args (argc, argv);
+
+ if (opt_install && !opt_remove)
+ {
+ if (-1 == SERVICE::instance ()->insert (opt_startup))
+ {
+ ACE_ERROR ((LM_ERROR, ACE_TEXT ("%p\n"), ACE_TEXT ("insert")));
+ return -1;
+ }
+ return 0;
+ }
+
+ if (opt_remove && !opt_install)
+ {
+ if (-1 == SERVICE::instance ()->remove ())
+ {
+ ACE_ERROR ((LM_ERROR, ACE_TEXT ("%p\n"), ACE_TEXT ("remove")));
+ return -1;
+ }
+ return 0;
+ }
+
+ if (opt_start && opt_kill)
+ print_usage_and_die ();
+
+ if (opt_start)
+ {
+ if (-1 == SERVICE::instance ()->start_svc ())
+ {
+ ACE_ERROR ((LM_ERROR, ACE_TEXT ("%p\n"), ACE_TEXT ("start")));
+ return -1;
+ }
+ return 0;
+ }
+
+ if (opt_kill)
+ {
+ if (-1 == SERVICE::instance ()->stop_svc ())
+ {
+ ACE_ERROR ((LM_ERROR, ACE_TEXT ("%p\n"), ACE_TEXT ("stop")));
+ return -1;
+ }
+ return 0;
+ }
+
+ if (opt_type)
+ {
+ if (-1 == SERVICE::instance ()->startup (opt_startup))
+ {
+ ACE_ERROR ((LM_ERROR, ACE_TEXT ("%p\n"), ACE_TEXT ("set startup")));
+ return -1;
+ }
+ return 0;
+ }
+
+ // If we get here, we either run the app in debug mode (-d) or are
+ // being called from the service manager to start the service.
+
+ if (opt_debug)
+ {
+ SetConsoleCtrlHandler (&ConsoleHandler, 1);
+ SERVICE::instance ()->svc ();
+ }
+ else
+ {
+ ofstream *output_file = new ofstream("ntsvc.log", ios::out);
+ if (output_file && output_file->rdstate() == ios::goodbit)
+ ACE_LOG_MSG->msg_ostream(output_file, 1);
+ ACE_LOG_MSG->open(argv[0],
+ ACE_Log_Msg::STDERR | ACE_Log_Msg::OSTREAM,
+ 0);
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("%T (%t): Starting service.\n")));
+
+ ACE_NT_SERVICE_RUN (Beeper,
+ SERVICE::instance (),
+ ret);
+ if (ret == 0)
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("Couldn't start service")));
+ else
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("%T (%t): Service stopped.\n")));
+ }
+
+ return 0;
+}
+
+int
+ACE_TMAIN (int argc, ACE_TCHAR* argv[])
+{
+ return PROCESS::instance ()->run (argc, argv);
+}
+
diff --git a/ACE/examples/NT_Service/ntsvc.cpp b/ACE/examples/NT_Service/ntsvc.cpp
new file mode 100644
index 00000000000..f21dec5dad7
--- /dev/null
+++ b/ACE/examples/NT_Service/ntsvc.cpp
@@ -0,0 +1,113 @@
+// $Id$
+
+// ============================================================================
+//
+// = LIBRARY
+// examples/NT_Service
+//
+// = FILENAME
+// ntsvc.cpp
+//
+// = DESCRIPTION
+// This is the implementation of the NT service. It beeps every 2
+// seconds until the service is stopped.
+//
+// = AUTHOR
+// Gonzalo Diethelm <gonzo@cs.wustl.edu>
+// and Steve Huston <shuston@riverace.com>
+//
+// ============================================================================
+
+#include "ace/Reactor.h"
+#include "ntsvc.h"
+
+Service::Service (void)
+{
+ // Remember the Reactor instance.
+ reactor (ACE_Reactor::instance ());
+}
+
+Service::~Service (void)
+{
+ if (ACE_Reactor::instance ()->cancel_timer(this) == -1)
+ ACE_ERROR ((LM_ERROR,
+ "Service::~Service failed to cancel_timer.\n"));
+}
+
+// This method is called when the service gets a control request. It
+// handles requests for stop and shutdown by calling terminate ().
+// All others get handled by calling up to inherited::handle_control.
+
+void
+Service::handle_control (DWORD control_code)
+{
+ if (control_code == SERVICE_CONTROL_SHUTDOWN
+ || control_code == SERVICE_CONTROL_STOP)
+ {
+ report_status (SERVICE_STOP_PENDING);
+
+ ACE_DEBUG ((LM_INFO,
+ ACE_TEXT ("Service control stop requested\n")));
+ stop_ = 1;
+ reactor ()->notify (this,
+ ACE_Event_Handler::EXCEPT_MASK);
+ }
+ else
+ inherited::handle_control (control_code);
+}
+
+// This is just here to be the target of the notify from above... it
+// doesn't do anything except aid on popping the reactor off its wait
+// and causing a drop out of handle_events.
+
+int
+Service::handle_exception (ACE_HANDLE)
+{
+ return 0;
+}
+
+// Beep every two seconds. This is what this NT service does...
+
+int
+Service::handle_timeout (const ACE_Time_Value &tv,
+ const void *)
+{
+ ACE_UNUSED_ARG (tv);
+ MessageBeep (MB_OK);
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("%T (%t): Beep...\n")));
+ return 0;
+}
+
+// This is the main processing function for the Service. It sets up
+// the initial configuration and runs the event loop until a shutdown
+// request is received.
+
+int
+Service::svc (void)
+{
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("Service::svc\n")));
+
+ // As an NT service, we come in here in a different thread than the
+ // one which created the reactor. So in order to do anything, we
+ // need to own the reactor. If we are not a service, report_status
+ // will return -1.
+ if (report_status (SERVICE_RUNNING) == 0)
+ reactor ()->owner (ACE_Thread::self ());
+
+ this->stop_ = 0;
+
+ // Schedule a timer every two seconds.
+ ACE_Time_Value tv (2, 0);
+ ACE_Reactor::instance ()->schedule_timer (this, 0, tv, tv);
+
+ while (!this->stop_)
+ reactor ()->handle_events ();
+
+ // Cleanly terminate connections, terminate threads.
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("Shutting down\n")));
+ reactor ()->cancel_timer (this);
+ return 0;
+}
+
diff --git a/ACE/examples/NT_Service/ntsvc.h b/ACE/examples/NT_Service/ntsvc.h
new file mode 100644
index 00000000000..cecc91b34c5
--- /dev/null
+++ b/ACE/examples/NT_Service/ntsvc.h
@@ -0,0 +1,65 @@
+/* -*- C++ -*- */
+// $Id$
+
+// ============================================================================
+//
+// = LIBRARY
+// examples/NT_Service
+//
+// = FILENAME
+// ntsvc.h
+//
+// = DESCRIPTION
+// This is the definition of the sample NT Service class. This example
+// only runs on Win32 platforms.
+//
+// = AUTHOR
+// Gonzalo Diethelm and Steve Huston
+//
+// ============================================================================
+
+#ifndef NTSVC_H_
+#define NTSVC_H_
+
+#include "ace/Event_Handler.h"
+#include "ace/NT_Service.h"
+#include "ace/Singleton.h"
+#include "ace/Mutex.h"
+
+class Service : public ACE_NT_Service
+{
+public:
+ Service (void);
+
+ ~Service (void);
+
+ virtual void handle_control (DWORD control_code);
+ // We override <handle_control> because it handles stop requests
+ // privately.
+
+ virtual int handle_exception (ACE_HANDLE h);
+ // We override <handle_exception> so a 'stop' control code can pop
+ // the reactor off of its wait.
+
+ virtual int svc (void);
+ // This is a virtual method inherited from ACE_NT_Service.
+
+ virtual int handle_timeout (const ACE_Time_Value& tv,
+ const void *arg = 0);
+ // Where the real work is done:
+
+private:
+ typedef ACE_NT_Service inherited;
+
+private:
+ int stop_;
+};
+
+// Define a singleton class as a way to insure that there's only one
+// Service instance in the program, and to protect against access from
+// multiple threads. The first reference to it at runtime creates it,
+// and the ACE_Object_Manager deletes it at run-down.
+
+typedef ACE_Singleton<Service, ACE_Mutex> SERVICE;
+
+#endif /* #ifndef NTSVC_H_ */
diff --git a/ACE/examples/Naming/.cvsignore b/ACE/examples/Naming/.cvsignore
new file mode 100644
index 00000000000..5e535209538
--- /dev/null
+++ b/ACE/examples/Naming/.cvsignore
@@ -0,0 +1,4 @@
+multiple_contexts
+non_existent
+open
+writers
diff --git a/ACE/examples/Naming/Makefile.am b/ACE/examples/Naming/Makefile.am
new file mode 100644
index 00000000000..de8e2353f18
--- /dev/null
+++ b/ACE/examples/Naming/Makefile.am
@@ -0,0 +1,90 @@
+## Process this file with automake to create Makefile.in
+##
+## $Id$
+##
+## This file was generated by MPC. Any changes made directly to
+## this file will be lost the next time it is generated.
+##
+## MPC Command:
+## /acebuilds/ACE_wrappers-repository/bin/mwc.pl -include /acebuilds/MPC/config -include /acebuilds/MPC/templates -feature_file /acebuilds/ACE_wrappers-repository/local.features -noreldefs -type automake -exclude build,Kokyu
+
+ACE_BUILDDIR = $(top_builddir)
+ACE_ROOT = $(top_srcdir)
+
+noinst_PROGRAMS =
+
+## Makefile.Naming_Multiple_Contexts.am
+
+if !BUILD_ACE_FOR_TAO
+noinst_PROGRAMS += multiple_contexts
+
+multiple_contexts_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+multiple_contexts_SOURCES = \
+ test_multiple_contexts.cpp
+
+multiple_contexts_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+endif !BUILD_ACE_FOR_TAO
+
+## Makefile.Naming_Non_Existent.am
+
+if !BUILD_ACE_FOR_TAO
+noinst_PROGRAMS += non_existent
+
+non_existent_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+non_existent_SOURCES = \
+ test_non_existent.cpp
+
+non_existent_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+endif !BUILD_ACE_FOR_TAO
+
+## Makefile.Naming_Open.am
+
+if !BUILD_ACE_FOR_TAO
+noinst_PROGRAMS += open
+
+open_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+open_SOURCES = \
+ test_open.cpp
+
+open_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+endif !BUILD_ACE_FOR_TAO
+
+## Makefile.Naming_Writers.am
+
+if !BUILD_ACE_FOR_TAO
+noinst_PROGRAMS += writers
+
+writers_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+writers_SOURCES = \
+ test_writers.cpp
+
+writers_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+endif !BUILD_ACE_FOR_TAO
+
+## Clean up template repositories, etc.
+clean-local:
+ -rm -f *~ *.bak *.rpo *.sym lib*.*_pure_* core core.*
+ -rm -f gcctemp.c gcctemp so_locations *.ics
+ -rm -rf cxx_repository ptrepository ti_files
+ -rm -rf templateregistry ir.out
+ -rm -rf ptrepository SunWS_cache Templates.DB
diff --git a/ACE/examples/Naming/Naming.mpc b/ACE/examples/Naming/Naming.mpc
new file mode 100644
index 00000000000..f8365ffe07d
--- /dev/null
+++ b/ACE/examples/Naming/Naming.mpc
@@ -0,0 +1,34 @@
+// -*- MPC -*-
+// $Id$
+
+project(*multiple_contexts) : aceexe {
+ avoids += ace_for_tao
+ exename = multiple_contexts
+ Source_Files {
+ test_multiple_contexts.cpp
+ }
+}
+
+project(*non_existent) : aceexe {
+ avoids += ace_for_tao
+ exename = non_existent
+ Source_Files {
+ test_non_existent.cpp
+ }
+}
+
+project(*writers) : aceexe {
+ avoids += ace_for_tao
+ exename = writers
+ Source_Files {
+ test_writers.cpp
+ }
+}
+
+project(*open) : aceexe {
+ avoids += ace_for_tao
+ exename = open
+ Source_Files {
+ test_open.cpp
+ }
+}
diff --git a/ACE/examples/Naming/test_multiple_contexts.cpp b/ACE/examples/Naming/test_multiple_contexts.cpp
new file mode 100644
index 00000000000..06cb4d1c376
--- /dev/null
+++ b/ACE/examples/Naming/test_multiple_contexts.cpp
@@ -0,0 +1,86 @@
+// $Id$
+
+#include "ace/OS_main.h"
+#include "ace/Naming_Context.h"
+#include "ace/Log_Msg.h"
+#include "ace/OS_NS_stdio.h"
+
+ACE_RCSID(Naming, test_multiple_contexts, "$Id$")
+
+int ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ static u_long ACE_DEFAULT_BASE_ADDR_1 = (1 * 64 * 1024 * 1024);
+ static u_long ACE_DEFAULT_BASE_ADDR_2 = (2 * 64 * 1024 * 1024);
+
+ int i;
+
+ ACE_STATIC_SVC_REGISTER(ACE_Naming_Context);
+
+ ACE_Naming_Context *ns_ptr;
+ ACE_NEW_RETURN (ns_ptr,
+ ACE_Naming_Context,
+ 1);
+ ACE_Name_Options *name_options =
+ ns_ptr->name_options ();
+
+ ACE_Naming_Context *ns_ptr1;
+ ACE_NEW_RETURN (ns_ptr1,
+ ACE_Naming_Context,
+ 1);
+ ACE_Name_Options *name_options1 =
+ ns_ptr1->name_options ();
+
+ ACE_TCHAR address_arg1[BUFSIZ];
+ ACE_TCHAR address_arg2[BUFSIZ];
+ ACE_OS::sprintf (address_arg1,
+ ACE_TEXT("-b%ld"),
+ ACE_DEFAULT_BASE_ADDR_1);
+
+ const ACE_TCHAR *m_argv[] =
+ {
+ ACE_TEXT("MyName1"),
+ ACE_TEXT("-cNODE_LOCAL"),
+ address_arg1,
+ NULL
+ };
+ int m_argc =
+ sizeof (m_argv) / sizeof (ACE_TCHAR *) -1;
+
+ ACE_OS::sprintf (address_arg2,
+ ACE_TEXT("-b%ld"),
+ ACE_DEFAULT_BASE_ADDR_2);
+ const ACE_TCHAR *n_argv[] =
+ {
+ ACE_TEXT("MyName2"),
+ ACE_TEXT("-cNODE_LOCAL"),
+ address_arg2,
+ NULL
+ };
+
+ int n_argc =
+ sizeof (n_argv) / sizeof (ACE_TCHAR *) -1;
+
+ name_options->parse_args (m_argc,
+ (ACE_TCHAR **) m_argv);
+ i = ns_ptr->open (ACE_Naming_Context::NODE_LOCAL);
+
+ ACE_DEBUG ((LM_DEBUG,
+ "(%P) opened with %d\n",
+ i));
+
+ if (i != 0)
+ return -1;
+
+ name_options1->parse_args (n_argc,
+ (ACE_TCHAR **) n_argv);
+
+ i = ns_ptr1->open (ACE_Naming_Context::NODE_LOCAL);
+
+ ACE_DEBUG ((LM_DEBUG,
+ "(%P) 1 opened with %d\n",
+ i));
+ if (i != 0)
+ return -1;
+
+ return 0;
+}
diff --git a/ACE/examples/Naming/test_non_existent.cpp b/ACE/examples/Naming/test_non_existent.cpp
new file mode 100644
index 00000000000..448594bd969
--- /dev/null
+++ b/ACE/examples/Naming/test_non_existent.cpp
@@ -0,0 +1,54 @@
+// $Id$
+
+#include "ace/OS_main.h"
+#include "ace/Naming_Context.h"
+#include "ace/Log_Msg.h"
+
+ACE_RCSID(Naming, test_non_existent, "$Id$")
+
+int ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ int i;
+
+ ACE_STATIC_SVC_REGISTER(ACE_Naming_Context);
+
+ ACE_Naming_Context *ns_ptr;
+ ACE_NEW_RETURN (ns_ptr,
+ ACE_Naming_Context,
+ 1);
+
+ ACE_Name_Options *name_options = ns_ptr->name_options ();
+
+ const ACE_TCHAR *m_argv[] =
+ {
+ ACE_TEXT("MyName"),
+ ACE_TEXT("-cNODE_LOCAL") ,
+#if defined (ACE_WIN32)
+ ACE_TEXT("-lC:\\temp\\non_existent"),
+#else
+ ACE_TEXT("-l/tmp/foobar.mine"),
+#endif /* ACE_WIN32 */
+ 0
+ };
+
+ int m_argc =
+ sizeof (m_argv) / sizeof (ACE_TCHAR *) -1;
+
+ name_options->parse_args (m_argc, (ACE_TCHAR**)m_argv);
+
+ i = ns_ptr->open (ACE_Naming_Context::NODE_LOCAL);
+ ACE_DEBUG ((LM_DEBUG,
+ "(%P) opened with %d\n",
+ i));
+ if (i != 0)
+ return -1;
+
+ i = ns_ptr->bind ("Key_Value",
+ "Val_Value",
+ "-");
+
+ ACE_DEBUG ((LM_DEBUG,
+ "(%P) bound with %d\n",
+ i));
+ return 0;
+}
diff --git a/ACE/examples/Naming/test_open.cpp b/ACE/examples/Naming/test_open.cpp
new file mode 100644
index 00000000000..247f3987112
--- /dev/null
+++ b/ACE/examples/Naming/test_open.cpp
@@ -0,0 +1,83 @@
+// $Id$
+
+#include "ace/OS_main.h"
+#include "ace/Naming_Context.h"
+#include "ace/Log_Msg.h"
+#include "ace/OS_NS_stdio.h"
+#include "ace/OS_NS_unistd.h"
+
+ACE_RCSID(Naming, test_open, "$Id$")
+
+int
+ACE_TMAIN (int argc, ACE_TCHAR **argv)
+{
+ const ACE_TCHAR *host = argc > 1 ? argv[1] : ACE_TEXT("-hlocalhost");
+ const ACE_TCHAR *port = argc > 2 ? argv[2] : ACE_TEXT("-p20012");
+
+ ACE_STATIC_SVC_REGISTER(ACE_Naming_Context);
+
+ ACE_Naming_Context ns;
+ ACE_Name_Options *name_options = ns.name_options ();
+
+ const ACE_TCHAR *m_argv[] =
+ {
+ ACE_TEXT("MyName"),
+ ACE_TEXT("-cNET_LOCAL"),
+ host,
+ port,
+ 0
+ };
+ int m_argc =
+ sizeof (m_argv) / sizeof (ACE_TCHAR *) -1;
+
+ name_options->parse_args (m_argc,
+ (ACE_TCHAR **) m_argv);
+
+ int result = ns.open (ACE_Naming_Context::NET_LOCAL);
+ ACE_DEBUG ((LM_DEBUG,
+ "ACE_Naming_Context::open returned %d\n",
+ result));
+ if (result != 0)
+ return result;
+ else
+ {
+ char key[128];
+ char val[32];
+ char type[2];
+
+ type[0] = '-';
+ type[1] = '\0';
+
+ int i = 0;
+
+ for (int l = 1; l <= 1000 ; l++)
+ {
+ ACE_OS::sprintf (key,
+ "K_%05d_%05d",
+ (int) ACE_OS::getpid (),
+ l);
+ ACE_OS::sprintf (val,
+ "Val%05d",
+ l);
+ i = ns.bind (key,
+ val,
+ type);
+ ACE_DEBUG ((LM_DEBUG,
+ "%d: bind of %s: %d\n",
+ ACE_OS::getpid (),
+ key,
+ i));
+
+ if (i != 0)
+ return -1;
+
+ }
+
+ result = ns.close ();
+ ACE_DEBUG ((LM_DEBUG,
+ "ACE_Naming_Context::close returned %d\n",
+ result));
+ }
+
+ return result;
+}
diff --git a/ACE/examples/Naming/test_writers.cpp b/ACE/examples/Naming/test_writers.cpp
new file mode 100644
index 00000000000..7277003ed2d
--- /dev/null
+++ b/ACE/examples/Naming/test_writers.cpp
@@ -0,0 +1,76 @@
+// $Id$
+
+#include "ace/OS_main.h"
+#include "ace/Naming_Context.h"
+#include "ace/Log_Msg.h"
+#include "ace/OS_NS_stdio.h"
+#include "ace/OS_NS_unistd.h"
+
+ACE_RCSID(Naming, test_writers, "$Id$")
+
+int ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ int i;
+
+ ACE_STATIC_SVC_REGISTER(ACE_Naming_Context);
+
+ ACE_Naming_Context *ns_ptr;
+ ACE_NEW_RETURN (ns_ptr,
+ ACE_Naming_Context,
+ 1);
+ ACE_Name_Options *name_options =
+ ns_ptr->name_options ();
+
+ const ACE_TCHAR *m_argv[] =
+ {
+ ACE_TEXT("MyName"),
+ ACE_TEXT("-cNODE_LOCAL"),
+ NULL
+ };
+
+ int m_argc = sizeof (m_argv) / sizeof (ACE_TCHAR *) -1;
+
+ name_options->parse_args (m_argc,
+ (ACE_TCHAR **) m_argv);
+ i = ns_ptr->open (ACE_Naming_Context::NODE_LOCAL);
+ ACE_DEBUG ((LM_DEBUG,
+ "(%P) opened with %d\n",
+ i));
+ if (i != 0)
+ return -1;
+ else
+ {
+ char key[128];
+ char val[32];
+ char type[2];
+
+ type[0] = '-';
+ type[1] = '\0';
+
+ int i = 0;
+
+ for (int l = 1; l <= 1000 ; l++)
+ {
+ ACE_OS::sprintf (key,
+ "K_%05d_%05d",
+ (int) ACE_OS::getpid (),
+ l);
+ ACE_OS::sprintf (val,
+ "Val%05d",
+ l);
+ i = ns_ptr->bind (key,
+ val,
+ type);
+ ACE_DEBUG ((LM_DEBUG,
+ "%d: bind of %s: %d\n",
+ ACE_OS::getpid (),
+ key,
+ i));
+
+ if (i != 0)
+ return -1;
+
+ }
+ }
+ return 0;
+}
diff --git a/ACE/examples/OS/Makefile.am b/ACE/examples/OS/Makefile.am
new file mode 100644
index 00000000000..73458dccc45
--- /dev/null
+++ b/ACE/examples/OS/Makefile.am
@@ -0,0 +1,13 @@
+## Process this file with automake to create Makefile.in
+##
+## $Id$
+##
+## This file was generated by MPC. Any changes made directly to
+## this file will be lost the next time it is generated.
+##
+## MPC Command:
+## /acebuilds/ACE_wrappers-repository/bin/mwc.pl -include /acebuilds/MPC/config -include /acebuilds/MPC/templates -feature_file /acebuilds/ACE_wrappers-repository/local.features -noreldefs -type automake -exclude build,Kokyu
+
+SUBDIRS = \
+ Process
+
diff --git a/ACE/examples/OS/Process/.cvsignore b/ACE/examples/OS/Process/.cvsignore
new file mode 100644
index 00000000000..c52eac932e5
--- /dev/null
+++ b/ACE/examples/OS/Process/.cvsignore
@@ -0,0 +1,4 @@
+imore
+imore
+process
+process
diff --git a/ACE/examples/OS/Process/Makefile.am b/ACE/examples/OS/Process/Makefile.am
new file mode 100644
index 00000000000..88eac9e35bd
--- /dev/null
+++ b/ACE/examples/OS/Process/Makefile.am
@@ -0,0 +1,52 @@
+## Process this file with automake to create Makefile.in
+##
+## $Id$
+##
+## This file was generated by MPC. Any changes made directly to
+## this file will be lost the next time it is generated.
+##
+## MPC Command:
+## /acebuilds/ACE_wrappers-repository/bin/mwc.pl -include /acebuilds/MPC/config -include /acebuilds/MPC/templates -feature_file /acebuilds/ACE_wrappers-repository/local.features -noreldefs -type automake -exclude build,Kokyu
+
+ACE_BUILDDIR = $(top_builddir)
+ACE_ROOT = $(top_srcdir)
+
+noinst_PROGRAMS =
+
+## Makefile.OS_Process_Imore.am
+
+if !BUILD_ACE_FOR_TAO
+noinst_PROGRAMS += imore
+
+imore_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+imore_SOURCES = \
+ imore.cpp
+
+imore_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+endif !BUILD_ACE_FOR_TAO
+
+## Makefile.OS_Process_Process.am
+noinst_PROGRAMS += process
+
+process_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+process_SOURCES = \
+ process.cpp
+
+process_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Clean up template repositories, etc.
+clean-local:
+ -rm -f *~ *.bak *.rpo *.sym lib*.*_pure_* core core.*
+ -rm -f gcctemp.c gcctemp so_locations *.ics
+ -rm -rf cxx_repository ptrepository ti_files
+ -rm -rf templateregistry ir.out
+ -rm -rf ptrepository SunWS_cache Templates.DB
diff --git a/ACE/examples/OS/Process/OS_Process.mpc b/ACE/examples/OS/Process/OS_Process.mpc
new file mode 100644
index 00000000000..082f7133301
--- /dev/null
+++ b/ACE/examples/OS/Process/OS_Process.mpc
@@ -0,0 +1,16 @@
+// -*- MPC -*-
+// $Id$
+
+project(*imore) : aceexe {
+ avoids += ace_for_tao
+ exename = imore
+ Source_Files {
+ imore.cpp
+ }
+}
+project(*process) : aceexe {
+ exename = process
+ Source_Files {
+ process.cpp
+ }
+}
diff --git a/ACE/examples/OS/Process/README b/ACE/examples/OS/Process/README
new file mode 100644
index 00000000000..c22757eb73f
--- /dev/null
+++ b/ACE/examples/OS/Process/README
@@ -0,0 +1,54 @@
+This directory contains two examples: <imore> and <process>. They
+show how you can play with various features of ACE_Process to create
+new processes.
+
+imore:
+-----
+This example shows how to redirect the output of one process (in our
+case, the parent process) to another process (child process.) This is
+very similiar what a UNIX shell does when we "pipe" command together.
+You can select whether you want to use named pipes or a unnamed pipe.
+
+
+process:
+--------
+
+This example shows how to use ACE_Process to "portably" create new
+processes. The ACE_Process_Options class allows applications to
+portably specify path, command-line arguments, environment variable
+values. It also allows applications to set the new process' standard
+handles (stdin, stdout, and stderr). ACE_Process is created with the
+ACE_Process_Options and can be used to perform operations on the
+running process.
+
+Notice that this example uses NT version's UNIX utilities like
+"DATE.EXE," and "ls.exe." You can find where to get them from
+Microsoft's NT page on the Web.
+
+Run the application as ./process -u to get all the command-line
+options.
+
+Here's an example output:
+
+lambada:OS/Process> ./process -a
+starting...
+starting...
+Sun May 11 15:06:51 CDT 1997
+date succeeded.
+starting...
+checking ACE_PROCESS_TEST
+ACE_PROCESS_TEST = here's a large number 4294967295.
+ACE_PROCESS_TEST2 = ophilli.
+total 600
+drwxr-xr-x 5 harrison doc 512 May 11 15:06 .
+drwxr-xr-x 4 harrison doc 512 Apr 21 15:32 ..
+drwx------ 2 harrison doc 512 May 8 22:33 .obj
+drwx------ 2 harrison doc 512 May 8 22:33 .shobj
+drwxr-xr-x 2 harrison doc 512 May 11 15:05 CVS
+-rw-r--r-- 1 harrison doc 1717 Oct 21 1996 Makefile
+-rw-r--r-- 1 harrison doc 10048 Oct 21 1996 Process.mak
+-rw-r--r-- 1 harrison doc 44032 Oct 21 1996 Process.mdp
+-rw-r--r-- 1 harrison doc 1452 May 11 15:05 README
+-rwx--x--x 1 harrison doc 212992 May 11 15:06 process
+-rw-r--r-- 1 harrison doc 10172 May 10 19:38 process.cpp
+-rw------- 1 harrison doc 1380 May 10 19:19 process.wst
diff --git a/ACE/examples/OS/Process/imore.cpp b/ACE/examples/OS/Process/imore.cpp
new file mode 100644
index 00000000000..181254e0cb4
--- /dev/null
+++ b/ACE/examples/OS/Process/imore.cpp
@@ -0,0 +1,267 @@
+// ============================================================================
+// $Id$
+//
+// = LIBRARY
+// examples
+//
+// = FILENAME
+// imore.cpp (imore stands for indirect more.)
+//
+// = DESCRIPTION
+// This program demonstrates how to redirect stdout of a parent
+// process to the stdin of its child process using either unnamed pipe
+// or named pipes to relay data to subprocess which runs "more" to
+// display data on the screen. Run imore to see how to use this
+// program.
+//
+// Unfortunately, on Win32, this program doesn't use any pipe at all because
+// using pipes confuses MORE.COM on Win32 and it just acts like "cat" on Unix.
+//
+// = AUTHOR
+// Nanbor Wang <nanbor@cs.wustl.edu>
+//
+// ============================================================================
+
+#include "ace/OS_NS_stdio.h"
+#include "ace/OS_NS_errno.h"
+#include "ace/OS_NS_unistd.h"
+#include "ace/OS_NS_fcntl.h"
+#include "ace/FIFO_Recv.h"
+#include "ace/FIFO_Send.h"
+#include "ace/Pipe.h"
+#include "ace/Get_Opt.h"
+#include "ace/Log_Msg.h"
+#include "ace/Process.h"
+#include "ace/Signal.h"
+
+ACE_RCSID(Process, imore, "$Id$")
+
+#if defined (ACE_WIN32)
+static const ACE_TCHAR *executable = ACE_TEXT("MORE.COM");
+static const ACE_TCHAR *rendezvous_dir = ACE_TEXT("c:/temp");
+static const ACE_TCHAR *rendezvous_pfx = ACE_TEXT("imore");
+#else
+static const char * executable = "more"; // I like less better.
+static const ACE_TCHAR *rendezvous_dir = ACE_TEXT("/tmp");
+static const ACE_TCHAR *rendezvous_pfx = ACE_TEXT("imore");
+#endif /* ACE_WIN32 */
+
+static ACE_TCHAR *fname = 0; // File you want to view.
+static int use_named_pipe = 0; // Do we want to use named pipe?
+
+static void
+usage (void)
+{
+ ACE_ERROR ((LM_ERROR, "Usage: imore [-n|-u] <filename>\n"
+ "\t-n Use named pipe.\n"
+ "\t-u Use unnamed pipe.\n"));
+}
+
+static int
+parse_args (int argc, ACE_TCHAR **argv)
+{
+ ACE_Get_Opt get_opt (argc, argv, ACE_TEXT("un"));
+ int c;
+
+ while ((c = get_opt ()) != -1)
+ {
+ switch (c)
+ {
+ case 'n': // We want to use named pipe.
+#if !defined (ACE_WIN32)
+ use_named_pipe = 1;
+#else
+ ACE_ERROR_RETURN ((LM_ERROR, "Named pipes not supported on Win32\n"), -1);
+#endif /* !ACE_WIN32 */
+ break;
+ case 'u': // Use unnamed pipe.
+ use_named_pipe = 0;
+ break;
+ default: // What are you talking about?
+ usage ();
+ return -1;
+ }
+ }
+
+ if (get_opt.opt_ind () >= argc) // Do you forget to give me a filename to "more?"
+ {
+ usage ();
+ return -1;
+ }
+ else
+ fname = argv[get_opt.opt_ind ()]; // Alright.
+
+ return 0;
+}
+
+static int
+setup_named_pipes (ACE_Process_Options &opt)
+{
+ // Create a unique temporary name for named pipe.
+ ACE_TCHAR *rendezvous = ACE_OS::tempnam (rendezvous_dir,
+ rendezvous_pfx);
+
+ // Out of memory?
+ if (rendezvous == NULL)
+ return -1;
+
+ // Alright, this is indeed strange. Named pipes are meant to be
+ // used for unrelated processes. Because of the constraints in
+ // ACE_Process, I have to pre-open the named pipes here.
+ ACE_FIFO_Recv rfifo; // read end fifo.
+ ACE_FIFO_Send wfifo; // write end fifo.
+
+ // Check if the pipes are created successfully.
+ if (rfifo.open (rendezvous) == -1 || wfifo.open (rendezvous) == -1)
+ {
+ ACE_OS::free (rendezvous);
+ ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "fifo.open"), -1);
+ }
+
+ // Remove (rm, del) the file after no one uses it any more.
+ ACE_OS::unlink (rendezvous);
+ ACE_OS::free (rendezvous);
+
+ // Setting up pipe between parent and child process. Use the read
+ // end of the named pipe as child process'es ACE_STDIN.
+ // ACE_Process_Options will keep copies (by dup) of fd's that we
+ // pass in. Notice that we have to specify child process to use
+ // ACE_STDOUT for output explicitly because we'll close it down in
+ // the line after. Child process will use whatever we use to dup2
+ // ACE_STDOUT as its stdout.
+ opt.set_handles (rfifo.get_handle (), ACE_STDOUT);
+
+ // The previous keep a copy of original ACE_STDOUT fd, now we
+ // can replace ACE_STDOUT of parent process to the write end
+ // of the named pipe.
+ ACE_OS::dup2 (wfifo.get_handle (), ACE_STDOUT);
+
+ // Close unused fd's. Notice ACE_FIFO doesn't close the fd
+ // when it goes out of scope.
+ rfifo.close ();
+ wfifo.close ();
+ return 0;
+}
+
+static int
+setup_unnamed_pipe (ACE_Process_Options &opt)
+{
+ // Create an unnamed pipe instance.
+ ACE_Pipe pipe;
+
+ // Check if the pipe is created successfully.
+ if (pipe.open () == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "pipe.open"), -1);
+
+ // Setting up pipe between parent and child process. Use the pipe
+ // as child process'es ACE_STDIN. ACE_Process_Options will keep
+ // copies (by dup) of fd's that we pass in. Notice that we have to
+ // specify child process to use ACE_STDOUT for output explicitly
+ // because we'll close it down in the line after. Child process
+ // will use whatever we use to dup2 ACE_STDOUT as its stdout.
+ opt.set_handles (pipe.read_handle (), ACE_STDOUT);
+
+ // The previous keep a copy of original ACE_STDOUT fd, now we
+ // can replace ACE_STDOUT of parent process to the pipe.
+ ACE_OS::dup2 (pipe.write_handle (), ACE_STDOUT);
+
+ // Don't forget to close the unused fd.
+ pipe.close ();
+ return 0;
+}
+
+static int
+print_file (ACE_HANDLE infd)
+{
+ char buffer[BUFSIZ];
+ ssize_t len;
+
+ while ((len = ACE_OS::read (infd, buffer, BUFSIZ)) > 0)
+ {
+ if ((ACE_OS::write (ACE_STDOUT, buffer, len) != len))
+ if (errno == EPIPE)
+ {
+ // I tried to "produce" EPIPE warning to test
+ // the program but never seen one. (odd.)
+ // ACE_ERROR ((LM_ERROR, "\n\nEPIPE\n"));
+ break;
+ }
+ else
+ ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "write"), -1);
+ }
+ return 0;
+}
+
+int
+ACE_TMAIN (int argc, ACE_TCHAR *argv[])
+{
+ // Ignore SIGPIPE signal on Unix platforms in case
+ // child process (more) terminates before we finish
+ // writing to stdout.
+#if !defined (ACE_WIN32)
+ ACE_Sig_Action sig_act (SIG_IGN);
+ if (sig_act.register_action (SIGPIPE) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "ACE_Sig_Action::register_action"), -1);
+#endif /* ACE_WIN32 */
+
+ // Alright, what you want me to do now?
+ if (::parse_args (argc, argv) == -1)
+ return -1;
+
+ // Can I find the file you want?
+ ACE_HANDLE infile = ACE_OS::open (fname, O_RDONLY);
+ if (infile == ACE_INVALID_HANDLE)
+ ACE_ERROR_RETURN ((LM_DEBUG, "%p\n", fname), -1);
+
+ ACE_Process new_process;
+
+ // Notice that we must enclose ACE_Process_Options in the block
+ // so the file handlers it keeps can be close elegantly.
+#if !defined (ACE_WIN32)
+ {
+ ACE_Process_Options options;
+
+ if ((use_named_pipe ? ::setup_named_pipes :
+ ::setup_unnamed_pipe) (options) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, "Error, bailing out!\n"), -1);
+
+ options.command_line (executable);
+ if (new_process.spawn (options) == -1)
+ {
+ int error = ACE_OS::last_error ();
+ ACE_ERROR_RETURN ((LM_ERROR, "%p errno = %d.\n",
+ "test_more", error), -1);
+ }
+ }
+
+ // write file to ACE_STDOUT.
+ if (::print_file (infile) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, "Error, bailing out!\n"), -1);
+
+ // Close the STDOUT to inform child eof.
+ ACE_OS::close (ACE_STDOUT);
+#else
+ // We can only pass a file handler directly to child process
+ // otherwise "more" doesn't act quite the way we want. Nonetheless,
+ // if your child process don't need to interact with the terminal,
+ // we can use the exact code for Unixes on NT.
+ ACE_Process_Options options;
+ options.command_line (executable);
+ options.set_handles (infile);
+ if (new_process.spawn (options) == -1)
+ {
+ int error = ACE_OS::last_error ();
+ ACE_ERROR_RETURN ((LM_ERROR, "%p errno = %d.\n",
+ "test_more", error), -1);
+ }
+#endif /* ! ACE_WIN32 */
+
+ // Wait till we are done.
+ ACE_exitcode status;
+ new_process.wait (&status);
+ ACE_DEBUG ((LM_DEBUG, "Process exit with status %d\n", status));
+
+ ACE_OS::close (infile);
+
+ return 0;
+}
diff --git a/ACE/examples/OS/Process/process.cpp b/ACE/examples/OS/Process/process.cpp
new file mode 100644
index 00000000000..de0f2db0d57
--- /dev/null
+++ b/ACE/examples/OS/Process/process.cpp
@@ -0,0 +1,577 @@
+// $Id$
+
+// ============================================================================
+//
+// = LIBRARY
+// examples
+//
+// = FILENAME
+// process.cpp
+//
+// = DESCRIPTION
+// This example tests the <ACE_Process>. For more info, check the
+// README file in this directory.
+//
+// = AUTHOR
+// Tim Harrison <harrison@cs.wustl.edu>.
+//
+// ============================================================================
+
+#include "ace/OS_NS_errno.h"
+#include "ace/OS_NS_fcntl.h"
+#include "ace/OS_NS_stdlib.h"
+#include "ace/OS_NS_stdio.h"
+#include "ace/OS_NS_string.h"
+#include "ace/OS_NS_unistd.h"
+#include "ace/Get_Opt.h"
+#include "ace/Process.h"
+#include "ace/Log_Msg.h"
+#include "ace/Time_Value.h"
+#include "ace/SString.h"
+
+ACE_RCSID(Process, process, "$Id$")
+
+#if defined (ACE_WIN32)
+#define EXEC_NAME ACE_TEXT ("MORE.COM")
+const ACE_TCHAR *DATE_PATH = ACE_TEXT ("date.exe");
+const ACE_TCHAR *LS_PATH = ACE_TEXT ("ls.exe");
+const ACE_TCHAR *SLEEP_PATH = ACE_TEXT ("sleep.exe");
+#else
+#define EXEC_NAME ACE_TEXT ("less")
+const ACE_TCHAR *DATE_PATH = ACE_TEXT ("date");
+const ACE_TCHAR *LS_PATH = ACE_TEXT ("ls");
+const ACE_TCHAR *SLEEP_PATH = ACE_TEXT ("sleep");
+#endif /* ACE_WIN32 */
+
+static const ACE_TCHAR *executable = EXEC_NAME;
+static ACE_TCHAR *print_file = 0;
+static ACE_TCHAR *environment_string = 0;
+static int get_env = 0;
+static int run_date = 0;
+static int run_ls = 0;
+static int run_all = 0;
+static int run_setenv = 0;
+static int run_tokenizer = 0;
+static int run_wait = 0;
+
+// Parse the command-line arguments and set options.
+static int
+parse_args (int argc, ACE_TCHAR **argv)
+{
+ ACE_Get_Opt get_opt (argc, argv, ACE_TEXT ("dlx:p:e:gastuw"));
+ int c;
+
+ while ((c = get_opt ()) != -1)
+ {
+ switch (c)
+ {
+ case 't':
+ run_tokenizer = 1;
+ break;
+ case 's':
+ run_setenv = 1;
+ break;
+ case 'a':
+ run_all = 1;
+ break;
+ case 'd':
+ run_date = 1;
+ break;
+ case 'l':
+ run_ls = 1;
+ break;
+ case 'x':
+ executable = get_opt.opt_arg ();
+ break;
+ case 'p':
+ print_file = get_opt.opt_arg ();
+ break;
+ case 'e':
+ environment_string = get_opt.opt_arg ();
+ break;
+ case 'g':
+ get_env = 1;
+ break;
+ case 'w':
+ run_wait = 1;
+ break;
+ case 'u':
+ default:
+ ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("Usage:\n")
+ ACE_TEXT ("-d print date\n")
+ ACE_TEXT ("-l run ls\n")
+ ACE_TEXT ("-x <executable=more.com>\n")
+ ACE_TEXT ("-p print <file_name>\n")
+ ACE_TEXT ("-e <env variable message>\n")
+ ACE_TEXT ("-s setenv ACE_PROCESS_ENV and spawn -g\n")
+ ACE_TEXT ("-g get_env ACE_PROCESS_ENV\n")
+ ACE_TEXT ("-t test tokenizer\n")
+ ACE_TEXT ("-w test wait functions\n")
+ ACE_TEXT ("-a run all (d,l,e \"running\")\n")),
+ -1);
+ break;
+ }
+ }
+
+ return 0;
+}
+
+// This shows how to set handles.
+static void
+test_more (void)
+{
+ ACE_HANDLE infile = ACE_OS::open (print_file, O_RDONLY);
+
+ if (infile == ACE_INVALID_HANDLE)
+ {
+ ACE_ERROR ((LM_DEBUG, ACE_TEXT ("%p\n"), print_file));
+ return;
+ }
+
+ ACE_Process new_process;
+ ACE_Process_Options options;
+ options.command_line (executable);
+ options.set_handles (infile);
+
+ if (new_process.spawn (options) == -1)
+ {
+ int error = ACE_OS::last_error ();
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("%p errno = %d.\n"),
+ ACE_TEXT ("test_more"),
+ error));
+ }
+
+ ACE_exitcode status;
+ new_process.wait (&status);
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("Process exit with status %d\n"),
+ status));
+ ACE_OS::close (infile);
+
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("More succeeded.\n")));
+}
+
+// This is a simple usage of ACE_Process.
+
+static void
+test_date (void)
+{
+ ACE_Process_Options options;
+ options.command_line (DATE_PATH);
+
+ // Try to create a new process running date.
+ ACE_Process new_process;
+ if (new_process.spawn (options) == -1)
+ {
+ int error = ACE_OS::last_error ();
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("%p errno = %d.\n"),
+ ACE_TEXT ("test_date"),
+ error));
+ return;
+ }
+
+ ACE_exitcode status;
+ new_process.wait (&status);
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("Process exit with status %d\n"),
+ status));
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("date succeeded.\n")));
+}
+
+static void
+test_ls (void)
+{
+ ACE_Process_Options options;
+#if defined (ACE_WIN32) || !defined (ACE_USES_WCHAR)
+ options.command_line (ACE_TEXT ("%s -al"), LS_PATH);
+#else
+ options.command_line (ACE_TEXT ("%ls -al"), LS_PATH);
+#endif
+ ACE_Process new_process;
+ if (new_process.spawn (options) == -1)
+ {
+ int error = ACE_OS::last_error ();
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("%p errno = %d.\n"),
+ ACE_TEXT ("test_ls"),
+ error));
+ }
+
+ ACE_exitcode status;
+ new_process.wait (&status);
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("Process exit with status %d\n"),
+ status));
+}
+
+static void
+test_wait (void)
+{
+ ACE_Process_Options options;
+#if defined (ACE_WIN32) || !defined (ACE_USES_WCHAR)
+ options.command_line (ACE_TEXT ("%s 10"), SLEEP_PATH);
+#else
+ options.command_line (ACE_TEXT ("%ls 10"), SLEEP_PATH);
+#endif
+ ACE_Process process1;
+ if (process1.spawn (options) == -1)
+ {
+ int error = ACE_OS::last_error ();
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("%p errno = %d.\n"),
+ ACE_TEXT ("test_ls"),
+ error));
+ }
+
+ int result;
+ ACE_exitcode status;
+
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("[%T] New process sleeping 10; try wait(2)\n")));
+
+ result = process1.wait (ACE_Time_Value (2), &status);
+
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("[%T] wait(2) returns %d(%d)...now try regular wait\n"),
+ result,
+ status));
+
+ result = process1.wait (&status);
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("[%T] wait() returns %d(%d)\n"),
+ result,
+ status));
+
+ ACE_Process process2;
+ if (process2.spawn (options) == -1)
+ {
+ int error = ACE_OS::last_error ();
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("%p errno = %d.\n"),
+ ACE_TEXT ("test_ls"),
+ error));
+ }
+
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("[%T] New process sleeping 10; try wait(12)\n"),
+ status));
+
+ result = process2.wait (ACE_Time_Value (12), &status);
+
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("[%T] wait(12) returns %d(%d)...now try regular wait\n"),
+ result,
+ status));
+
+ result = process2.wait (&status);
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("[%T] wait returns %d(%d)\n"),
+ result,
+ status));
+}
+
+#if defined (ACE_WIN32)
+// This is just to test the direct usage of CreateProcess. I use this
+// occasionally as a sanity check when ACE_Process breaks.
+static void
+win32_test_ls (void)
+{
+ PROCESS_INFORMATION process_info;
+ ACE_TEXT_STARTUPINFO startup_info;
+ ACE_OS::memset ((void *) &startup_info,
+ 0,
+ sizeof startup_info);
+ ACE_OS::memset ((void *) &process_info,
+ 0,
+ sizeof process_info);
+ startup_info.cb = sizeof startup_info;
+ startup_info.dwFlags = STARTF_USESTDHANDLES;
+
+ ACE_HANDLE std_out = ACE_STDOUT;
+
+ if (!::DuplicateHandle (::GetCurrentProcess (),
+ std_out,
+ ::GetCurrentProcess (),
+ &startup_info.hStdOutput,
+ 0,
+ TRUE,
+ DUPLICATE_SAME_ACCESS))
+ {
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("%p duplicate failed.\n"),
+ ACE_TEXT ("test_ls")));
+ return;
+ }
+
+ BOOL fork_result =
+ ACE_TEXT_CreateProcess (ACE_TEXT ("c:\\Utils\\bin\\ls.exe"),
+ ACE_TEXT ("-a"),
+ NULL, // No process attributes.
+ NULL, // No thread attributes.
+ TRUE, // Allow handle inheritance.
+ 0, // CREATE_NEW_CONSOLE, // Create a new console window.
+ NULL,
+ 0, // Current directory to start in.
+ &startup_info,
+ &process_info);
+
+ ::CloseHandle (startup_info.hStdOutput);
+
+ if (fork_result == 0)
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("%p CreateProcess failed.\n"),
+ ACE_TEXT ("test_ls")));
+ else
+ {
+ ::WaitForSingleObject (process_info.hProcess,
+ INFINITE);
+ ACE_DEBUG ((LM_ERROR, ACE_TEXT ("ls succeeded.\n")));
+ }
+}
+
+// This code spawns a new process. The new process inherits our
+// existing environment, plus one more. This has to be done by hand
+// since CreateProcess does not allow us to inherit AND add
+// environment variables.
+
+static void
+win32_spawn_environment_process (void)
+{
+ PROCESS_INFORMATION process_info;
+ ACE_TEXT_STARTUPINFO startup_info;
+ ACE_OS::memset ((void *) &startup_info,
+ 0,
+ sizeof startup_info);
+ ACE_OS::memset ((void *) &process_info,
+ 0,
+ sizeof process_info);
+ startup_info.cb = sizeof (startup_info);
+ startup_info.dwFlags = STARTF_USESTDHANDLES;
+
+ ACE_HANDLE std_in = ACE_STDIN;
+ ACE_HANDLE std_out = ACE_STDOUT;
+ ACE_HANDLE std_err = ACE_STDERR;
+
+ if (!::DuplicateHandle (::GetCurrentProcess(),
+ std_out,
+ ::GetCurrentProcess(),
+ &startup_info.hStdOutput,
+ 0,
+ TRUE,
+ DUPLICATE_SAME_ACCESS))
+ {
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("%p duplicate failed.\n"),
+ ACE_TEXT ("spawn_environment_process")));
+ return;
+ }
+
+ if (!::DuplicateHandle (::GetCurrentProcess(),
+ std_err,
+ ::GetCurrentProcess(),
+ &startup_info.hStdError,
+ 0,
+ TRUE,
+ DUPLICATE_SAME_ACCESS))
+ {
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("%p duplicate failed.\n"),
+ ACE_TEXT ("spawn_environment_process")));
+ return;
+ }
+
+ if (!::DuplicateHandle (::GetCurrentProcess(),
+ std_in,
+ ::GetCurrentProcess(),
+ &startup_info.hStdInput,
+ 0,
+ TRUE,
+ DUPLICATE_SAME_ACCESS))
+ {
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("%p duplicate failed.\n"),
+ ACE_TEXT ("spawn_environment_process")));
+ return;
+ }
+
+ // Normally, this would be just GetEnvironmentStrings, but it
+ // doesn't follow the same rules as the rest of the Win32 API
+ ACE_TCHAR *existing_environment = ACE_OS::getenvstrings ();
+ ACE_TCHAR environment[10240];
+ ACE_OS::sprintf (environment,
+ ACE_TEXT("ACE_PROCESS_TEST=%s"),
+ environment_string);
+
+ int size = 0;
+ while (existing_environment[size] != '\0')
+ size += ACE_OS::strlen (existing_environment + size) + 1;
+
+ ACE_OS::memcpy (environment + (ACE_OS::strlen (environment) + 1),
+ existing_environment,
+ size);
+
+ ACE_TEXT_FreeEnvironmentStrings (existing_environment);
+
+ BOOL fork_result =
+ ACE_TEXT_CreateProcess (ACE_TEXT ("d:\\harrison\\ACE_wrappers\\examples\\OS\\Process\\process.exe"),
+ ACE_TEXT ("process -g"),
+ NULL, // No process attributes.
+ NULL, // No thread attributes.
+ TRUE, // Allow handle inheritance.
+ 0, // CREATE_NEW_CONSOLE, // Create a new console window.
+ environment, // Environment.
+ //"d:\\harrison\\ACE_wrappers\\examples\\OS\\Process\\",
+ 0,
+ &startup_info,
+ &process_info);
+
+ ::CloseHandle (startup_info.hStdOutput);
+ ::CloseHandle (startup_info.hStdError);
+
+ if (fork_result == 0)
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("%p.\n"),
+ ACE_TEXT ("spawn_environment_process")));
+ else
+ {
+ ::WaitForSingleObject (process_info.hProcess,
+ INFINITE);
+ ACE_DEBUG ((LM_ERROR,
+ ACE_TEXT ("spawn_environment_process succeeded.\n")));
+ }
+}
+#endif
+
+static void
+test_setenv (const ACE_TCHAR *argv0)
+{
+ ACE_Process_Options options;
+ // options.setenv ("ACE_PROCESS_TEST", "here's a really large number: %u", 0 - 1);
+ options.setenv (ACE_TEXT ("ACE_PROCESS_TEST= here's a large number %u"),
+ 0 - 1);
+ options.setenv (ACE_TEXT ("ACE_PROCESS_TEST2"), ACE_TEXT ("ophilli"));
+#if defined (ACE_WIN32) || !defined (ACE_USES_WCHAR)
+ options.command_line ("%s -g", argv0);
+#else
+ options.command_line ("%ls -g", argv0);
+#endif
+ ACE_Process process;
+ if (process.spawn (options) == -1)
+ {
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("%p.\n"),
+ ACE_TEXT ("test_setenv")));
+ return;
+ }
+
+ ACE_exitcode status;
+ process.wait (&status);
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("Process exit with status %d\n"),
+ status));
+}
+
+// Tests the ACE_Tokenizer.
+static void
+tokenize (ACE_TCHAR *buffer)
+{
+ // This tokenizer will replace all spaces with end-of-string
+ // characters and will preserve text between "" and '' pairs.
+ ACE_Tokenizer parser (buffer);
+ parser.delimiter_replace (' ', '\0');
+ parser.preserve_designators ('\"', '\"'); // " This quote is for emacs
+ parser.preserve_designators ('\'', '\'');
+
+ for (const ACE_TCHAR *temp; ;)
+ {
+ temp = parser.next ();
+ if (temp == 0)
+ break;
+ ACE_DEBUG ((LM_DEBUG, temp));
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\n")));
+ }
+}
+
+int
+ACE_TMAIN (int argc, ACE_TCHAR *argv[])
+{
+ if (ACE_LOG_MSG->open (argv[0]) == -1)
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("cannot open logger!!!\n")));
+
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("starting...\n")));
+
+ if (::parse_args (argc, argv) == -1)
+ return -1;
+
+ if (run_all)
+ {
+#if defined (ACE_WIN32) || !defined (ACE_USES_WCHAR)
+ const ACE_TCHAR *cmdline = ACE_TEXT ("%s -d -l -s -w");
+#else
+ const ACE_TCHAR *cmdline = ACE_TEXT ("%ls -d -l -s -w");
+#endif
+ ACE_Process_Options options;
+ options.command_line (cmdline, argv[0]);
+ ACE_Process process;
+ if (process.spawn (options) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p.\n"),
+ ACE_TEXT ("main")),
+ -1);
+ ACE_exitcode status;
+ process.wait (&status);
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("Process exit with status %d\n"),
+ status));
+ }
+
+ if (run_date)
+ ::test_date ();
+
+ if (run_setenv)
+ ::test_setenv (argv[0]);
+
+ if (get_env)
+ {
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("checking ACE_PROCESS_TEST\n")));
+ char *value = ACE_OS::getenv ("ACE_PROCESS_TEST");
+ char *value2 = ACE_OS::getenv ("ACE_PROCESS_TEST2");
+ ACE_DEBUG ((LM_DEBUG,
+ "ACE_PROCESS_TEST = %C.\n"
+ "ACE_PROCESS_TEST2 = %C.\n",
+ value == 0 ? "no value" : value,
+ value2 == 0 ? "no value" : value2));
+ }
+
+ if (run_ls)
+ ::test_ls ();
+
+ if (run_wait)
+ ::test_wait ();
+
+#if defined (ACE_WIN32)
+ if (environment_string != 0)
+ win32_spawn_environment_process ();
+#endif /* ACE_WIN32 */
+
+ if (print_file != 0)
+ test_more ();
+
+ ACE_TCHAR buf1[30];
+ ACE_TCHAR buf2[30];
+ ACE_OS::strcpy(buf1, ACE_TEXT (" -f hi honey -g \"I\'m home\""));
+ ACE_OS::strcpy(buf2, ACE_TEXT ("\"token 1\"\'token 2\'\"token 3\" "));
+
+ if (run_tokenizer)
+ {
+ tokenize (buf1);
+ tokenize (buf2);
+ }
+
+ return 0;
+}
diff --git a/ACE/examples/QOS/Change_Receiver_FlowSpec/Fill_ACE_QoS.cpp b/ACE/examples/QOS/Change_Receiver_FlowSpec/Fill_ACE_QoS.cpp
new file mode 100644
index 00000000000..20c03f40fa6
--- /dev/null
+++ b/ACE/examples/QOS/Change_Receiver_FlowSpec/Fill_ACE_QoS.cpp
@@ -0,0 +1,99 @@
+// Fill_ACE_QoS.cpp
+// $Id$
+
+#include "Fill_ACE_QoS.h"
+
+ACE_RCSID(QOS, Fill_ACE_QoS,"$Id$")
+
+const iovec Fill_ACE_QoS::iov_ = {0,0};
+
+Fill_ACE_QoS::Fill_ACE_QoS (void)
+{
+ ACE_NEW (this->default_traffic_,
+ ACE_Flow_Spec (ACE_QOS_NOT_SPECIFIED,
+ ACE_QOS_NOT_SPECIFIED,
+ ACE_QOS_NOT_SPECIFIED,
+ ACE_QOS_NOT_SPECIFIED,
+ ACE_QOS_NOT_SPECIFIED,
+ ACE_SERVICETYPE_NOTRAFFIC,
+ ACE_QOS_NOT_SPECIFIED,
+ ACE_QOS_NOT_SPECIFIED,
+ 25,
+ 1));
+}
+
+// destructor.
+Fill_ACE_QoS::~Fill_ACE_QoS (void)
+{}
+
+int
+Fill_ACE_QoS::fill_simplex_receiver_qos (ACE_QoS &ace_qos,
+ const ACE_CString &recv_flow_name)
+{
+ ACE_Flow_Spec *recv_flow_spec = 0;
+
+ if (this->map ().find (recv_flow_name, recv_flow_spec) != 0)
+ ACE_ERROR_RETURN ((LM_DEBUG,
+ "Unable to find a FlowSpec with name %s",
+ recv_flow_name.c_str ()),
+ -1);
+ ace_qos.receiving_flowspec (recv_flow_spec);
+ ace_qos.sending_flowspec ((this->default_traffic_));
+ ace_qos.provider_specific (Fill_ACE_QoS::iov_);
+
+ return 0;
+}
+
+
+int
+Fill_ACE_QoS::fill_simplex_sender_qos (ACE_QoS &ace_qos,
+ const ACE_CString &send_flow_name)
+{
+ ACE_Flow_Spec *send_flow_spec = 0;
+
+ if (this->map ().find (send_flow_name, send_flow_spec) != 0)
+ ACE_ERROR_RETURN ((LM_DEBUG,
+ "Unable to find a FlowSpec with name %s",
+ send_flow_name.c_str ()),
+ -1);
+
+ ace_qos.receiving_flowspec ((this->default_traffic_));
+ ace_qos.sending_flowspec (send_flow_spec);
+ ace_qos.provider_specific (Fill_ACE_QoS::iov_);
+
+ return 0;
+}
+
+int
+Fill_ACE_QoS::fill_duplex_qos (ACE_QoS &ace_qos,
+ const ACE_CString &recv_flow_name,
+ const ACE_CString &send_flow_name)
+{
+ ACE_Flow_Spec *send_flow_spec = 0;
+ ACE_Flow_Spec *recv_flow_spec = 0;
+
+ if (this->map ().find (recv_flow_name, recv_flow_spec) != 0)
+ ACE_ERROR_RETURN ((LM_DEBUG,
+ "Unable to find a FlowSpec with name %s",
+ recv_flow_name.c_str ()),
+ -1);
+
+ if (this->map ().find (send_flow_name, send_flow_spec) != 0)
+ ACE_ERROR_RETURN ((LM_DEBUG,
+ "Unable to find a FlowSpec with name %s",
+ send_flow_name.c_str ()),
+ -1);
+
+ ace_qos.receiving_flowspec (recv_flow_spec);
+ ace_qos.sending_flowspec (send_flow_spec);
+ ace_qos.provider_specific (Fill_ACE_QoS::iov_);
+
+ return 0;
+}
+
+Fill_ACE_QoS::FLOW_SPEC_HASH_MAP&
+Fill_ACE_QoS::map (void)
+{
+ return this->flow_spec_map_;
+}
+
diff --git a/ACE/examples/QOS/Change_Receiver_FlowSpec/Fill_ACE_QoS.h b/ACE/examples/QOS/Change_Receiver_FlowSpec/Fill_ACE_QoS.h
new file mode 100644
index 00000000000..cdc06cea422
--- /dev/null
+++ b/ACE/examples/QOS/Change_Receiver_FlowSpec/Fill_ACE_QoS.h
@@ -0,0 +1,76 @@
+/* -*- C++ -*- */
+// $Id$
+
+// ============================================================================
+//
+// = LIBRARY
+// ACE_wrappers/examples/QOS
+//
+// = FILENAME
+// Fill_ACE_QoS.h
+//
+// = AUTHOR
+// Vishal Kachroo <vishal@cs.wustl.edu>
+//
+// ============================================================================
+
+#ifndef FILL_ACE_QOS_H
+#define FILL_ACE_QOS_H
+
+#include "ace/SString.h"
+#include "ace/Hash_Map_Manager.h"
+#include "ace/Synch_Traits.h"
+#include "ace/Null_Mutex.h"
+#include "ace/ACE.h"
+#include "ace/OS_QoS.h"
+
+class Fill_ACE_QoS
+{
+ // TITLE
+ // This class helps users to add new flow specs and provides
+ // utility functions for filling up the flow specs for simplex/duplex
+ // sessions.
+
+public:
+ typedef ACE_Hash_Map_Manager <ACE_CString, ACE_Flow_Spec *, ACE_Null_Mutex> FLOW_SPEC_HASH_MAP;
+
+ //Initialization and termination methods.
+ Fill_ACE_QoS (void);
+ // constructor.
+
+ ~Fill_ACE_QoS (void);
+ // destructor.
+
+ int fill_simplex_receiver_qos (ACE_QoS &ace_qos,
+ const ACE_CString &recv_flow_name);
+ // To be used by receivers. Fills the receiver qos and sets the
+ // sender qos to NO_TRAFFIC.
+
+ int fill_simplex_sender_qos (ACE_QoS &ace_qos,
+ const ACE_CString &send_flow_name);
+ // To be used by senders. Fills the sender qos and sets the receiver
+ // qos to NO_TRAFFIC.
+
+ int fill_duplex_qos (ACE_QoS &ace_qos,
+ const ACE_CString &recv_flow_name,
+ const ACE_CString &send_flow_name);
+ // To be used by applications that wish to be both receivers and
+ // senders.
+
+ FLOW_SPEC_HASH_MAP& map (void);
+ // Returns the hash map of flowspecs indexed by flowspec name.
+
+private:
+
+ // The Service Provider is currently set to NULL for all ACE_QoS.
+ static const iovec iov_;
+
+ // A NO_TRAFFIC flow spec. Senders set the receiving qos to this
+ // while the receivers set the sending qos to this.
+ ACE_Flow_Spec *default_traffic_;
+
+ // A list of flowspecs indexed by the flowspec name.
+ FLOW_SPEC_HASH_MAP flow_spec_map_;
+};
+
+#endif /* FILL_ACE_QOS_H */
diff --git a/ACE/examples/QOS/Change_Receiver_FlowSpec/FlowSpec_Dbase.h b/ACE/examples/QOS/Change_Receiver_FlowSpec/FlowSpec_Dbase.h
new file mode 100644
index 00000000000..fc382048c13
--- /dev/null
+++ b/ACE/examples/QOS/Change_Receiver_FlowSpec/FlowSpec_Dbase.h
@@ -0,0 +1,52 @@
+/* -*- C++ -*- */
+//$Id$
+
+// ============================================================================
+//
+// = LIBRARY
+// ACE_wrappers/examples/QOS
+//
+// = FILENAME
+// FlowSpec_Dbase.h
+//
+// = AUTHOR
+// Vishal Kachroo <vishal@cs.wustl.edu>
+//
+// ============================================================================
+
+#ifndef FLOWSPEC_DBASE_H
+#define FLOWSPEC_DBASE_H
+
+// This file contains the different FlowSpecs that the QoS enabled
+// application uses. Its a good idea to list them all here so the
+// application code is clean.
+
+ACE_Flow_Spec notraffic (ACE_QOS_NOT_SPECIFIED,
+ ACE_QOS_NOT_SPECIFIED,
+ ACE_QOS_NOT_SPECIFIED,
+ ACE_QOS_NOT_SPECIFIED,
+ ACE_QOS_NOT_SPECIFIED,
+ ACE_SERVICETYPE_NOTRAFFIC,
+ ACE_QOS_NOT_SPECIFIED,
+ ACE_QOS_NOT_SPECIFIED,
+ 25,
+ 1);
+
+ACE_Flow_Spec g711 (9200,
+ 708,
+ 18400,
+ 0,
+ 0,
+ ACE_SERVICETYPE_CONTROLLEDLOAD,
+ 368,
+ 368,
+ 25,
+ 1);
+
+// The default session address is macarena.cs.wustl.edu. I am using macarena
+// as my receiver for testing.
+#define DEFAULT_QOS_SESSION_MACHINE "128.252.165.127"
+#define DEFAULT_QOS_SESSION_PORT 8001
+
+#endif /* FLOWSPEC_DBASE_H */
+
diff --git a/ACE/examples/QOS/Change_Receiver_FlowSpec/Makefile.am b/ACE/examples/QOS/Change_Receiver_FlowSpec/Makefile.am
new file mode 100644
index 00000000000..c4d51897787
--- /dev/null
+++ b/ACE/examples/QOS/Change_Receiver_FlowSpec/Makefile.am
@@ -0,0 +1,76 @@
+## Process this file with automake to create Makefile.in
+##
+## $Id$
+##
+## This file was generated by MPC. Any changes made directly to
+## this file will be lost the next time it is generated.
+##
+## MPC Command:
+## /acebuilds/ACE_wrappers-repository/bin/mwc.pl -include /acebuilds/MPC/config -include /acebuilds/MPC/templates -feature_file /acebuilds/ACE_wrappers-repository/local.features -noreldefs -type automake -exclude build,Kokyu
+
+ACE_BUILDDIR = $(top_builddir)
+ACE_ROOT = $(top_srcdir)
+
+noinst_PROGRAMS =
+
+## Makefile.QOS_Change_Receiver_FlowSpec_Receiver.am
+
+if BUILD_QOS
+noinst_PROGRAMS += receiver
+
+receiver_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR) \
+ -DACE_HAS_QOS
+
+receiver_SOURCES = \
+ Fill_ACE_QoS.cpp \
+ QoS_Signal_Handler.cpp \
+ QoS_Util.cpp \
+ Receiver_QoS_Event_Handler.cpp \
+ receiver.cpp \
+ Fill_ACE_QoS.h \
+ QoS_Signal_Handler.h \
+ QoS_Util.h \
+ Receiver_QoS_Event_Handler.h
+
+receiver_LDADD = \
+ $(ACE_BUILDDIR)/ace/QoS/libACE_QoS.la \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+endif BUILD_QOS
+
+## Makefile.QOS_Change_Receiver_FlowSpec_Sender.am
+
+if BUILD_QOS
+noinst_PROGRAMS += sender
+
+sender_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR) \
+ -DACE_HAS_QOS
+
+sender_SOURCES = \
+ Fill_ACE_QoS.cpp \
+ QoS_Signal_Handler.cpp \
+ QoS_Util.cpp \
+ Sender_QoS_Event_Handler.cpp \
+ sender.cpp \
+ Fill_ACE_QoS.h \
+ QoS_Signal_Handler.h \
+ QoS_Util.h \
+ Sender_QoS_Event_Handler.h
+
+sender_LDADD = \
+ $(ACE_BUILDDIR)/ace/QoS/libACE_QoS.la \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+endif BUILD_QOS
+
+## Clean up template repositories, etc.
+clean-local:
+ -rm -f *~ *.bak *.rpo *.sym lib*.*_pure_* core core.*
+ -rm -f gcctemp.c gcctemp so_locations *.ics
+ -rm -rf cxx_repository ptrepository ti_files
+ -rm -rf templateregistry ir.out
+ -rm -rf ptrepository SunWS_cache Templates.DB
diff --git a/ACE/examples/QOS/Change_Receiver_FlowSpec/QOS_Change_Receiver_FlowSpec.mpc b/ACE/examples/QOS/Change_Receiver_FlowSpec/QOS_Change_Receiver_FlowSpec.mpc
new file mode 100644
index 00000000000..9767bd6fdb9
--- /dev/null
+++ b/ACE/examples/QOS/Change_Receiver_FlowSpec/QOS_Change_Receiver_FlowSpec.mpc
@@ -0,0 +1,25 @@
+// -*- MPC -*-
+// $Id$
+
+project(*receiver) : aceexe, qos {
+ exename = receiver
+ requires += qos
+ Source_Files {
+ Fill_ACE_QoS.cpp
+ QoS_Signal_Handler.cpp
+ QoS_Util.cpp
+ receiver.cpp
+ Receiver_QoS_Event_Handler.cpp
+ }
+}
+project(*sender) : aceexe, qos {
+ exename = sender
+ requires += qos
+ Source_Files {
+ Fill_ACE_QoS.cpp
+ QoS_Signal_Handler.cpp
+ QoS_Util.cpp
+ sender.cpp
+ Sender_QoS_Event_Handler.cpp
+ }
+}
diff --git a/ACE/examples/QOS/Change_Receiver_FlowSpec/QoS_Signal_Handler.cpp b/ACE/examples/QOS/Change_Receiver_FlowSpec/QoS_Signal_Handler.cpp
new file mode 100644
index 00000000000..9f07ad5b378
--- /dev/null
+++ b/ACE/examples/QOS/Change_Receiver_FlowSpec/QoS_Signal_Handler.cpp
@@ -0,0 +1,34 @@
+// QoS_Signal_Handler.cpp
+// $Id$
+
+#include "ace/Log_Msg.h"
+#include "QoS_Signal_Handler.h"
+
+ACE_RCSID(QOS, QoS_Signal_Handler,"$Id$")
+
+// constructor.
+QoS_Signal_Handler::QoS_Signal_Handler (ACE_QoS_Session *qos_session)
+ : qos_session_ (qos_session)
+{
+}
+
+// Releases the QoS sessions gracefully.
+int
+QoS_Signal_Handler::handle_signal (int signum, siginfo_t *, ucontext_t*)
+{
+ if (signum == SIGINT)
+ {
+ if (this->qos_session_->close () == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Unable to close the QoS session.\n"),
+ -1);
+ else
+ ACE_DEBUG ((LM_DEBUG,
+ "QoS Session with id %d closed successfully.\n",
+ this->qos_session_->session_id ()));
+ }
+ else
+ ACE_DEBUG ((LM_DEBUG,
+ "A signal other than SIGINT received.\nIgnoring.\n"));
+ return 0;
+}
diff --git a/ACE/examples/QOS/Change_Receiver_FlowSpec/QoS_Signal_Handler.h b/ACE/examples/QOS/Change_Receiver_FlowSpec/QoS_Signal_Handler.h
new file mode 100644
index 00000000000..35b9f3a19e7
--- /dev/null
+++ b/ACE/examples/QOS/Change_Receiver_FlowSpec/QoS_Signal_Handler.h
@@ -0,0 +1,45 @@
+/* -*- C++ -*- */
+// $Id$
+
+// =====================================================================
+//
+// = LIBRARY
+// ACE_wrappers/examples/QOS
+//
+// = FILENAME
+// QoS_Signal_Handler.h
+//
+// = AUTHOR
+// Vishal Kachroo <vishal@cs.wustl.edu>
+//
+// =====================================================================
+
+#ifndef QOS_SIGNAL_HANDLER_H
+#define QOS_SIGNAL_HANDLER_H
+
+#include "ace/Event_Handler.h"
+#include "ace/QoS/QoS_Session.h"
+
+class QoS_Signal_Handler : public ACE_Event_Handler
+{
+ // TITLE
+ // This class Handles the SIGINT signal through the Reactor.
+ // Useful to gracefully release QoS sessions.
+
+public:
+
+ QoS_Signal_Handler (ACE_QoS_Session *qos_session);
+ // constructor.
+
+ int handle_signal(int signum, siginfo_t*,ucontext_t*);
+ // Override this method to implement graceful shutdown.
+
+private:
+
+ ACE_QoS_Session *qos_session_;
+ // Session to be gracefully shutdown.
+
+};
+
+#endif /* QOS_SIGNAL_HANDLER_H */
+
diff --git a/ACE/examples/QOS/Change_Receiver_FlowSpec/QoS_Util.cpp b/ACE/examples/QOS/Change_Receiver_FlowSpec/QoS_Util.cpp
new file mode 100644
index 00000000000..0ef3b353248
--- /dev/null
+++ b/ACE/examples/QOS/Change_Receiver_FlowSpec/QoS_Util.cpp
@@ -0,0 +1,122 @@
+// QoS_Session_Impl.cpp
+// $Id$
+
+#define SENDER_PORT 10001
+
+#include "ace/Log_Msg.h"
+#include "ace/Get_Opt.h"
+#include "QoS_Util.h"
+#include "ace/OS_NS_strings.h"
+
+ACE_RCSID(QOS, QoS_Util,"$Id$")
+
+// constructor.
+QoS_Util::QoS_Util (int argc,
+ ACE_TCHAR *argv[])
+ : argc_ (argc),
+ argv_ (argv),
+ source_port_ (SENDER_PORT),
+ protocol_ (IPPROTO_UDP),
+ multicast_flag_ (0)
+{
+ ACE_NEW (this->mult_session_addr_,
+ ACE_INET_Addr (ACE_DEFAULT_MULTICAST_PORT));
+
+ ACE_NEW (this->dest_addr_,
+ ACE_INET_Addr (ACE_DEFAULT_SERVER_PORT));
+}
+
+// destructor.
+QoS_Util::~QoS_Util (void)
+{
+ delete this->mult_session_addr_;
+ delete this->dest_addr_;
+}
+
+int
+QoS_Util::parse_args (void)
+{
+ ACE_Get_Opt get_opts (this->argc_, this->argv_, ACE_TEXT("m:n:p:P:c"));
+ int c = 0;
+
+ while ((c = get_opts ()) != -1)
+ switch (c)
+ {
+ case 'm': // multicast session address.
+ this->multicast_flag_ = 1;
+ this->mult_session_addr_->set (get_opts.opt_arg ());
+ break;
+ case 'n': // to be used by Senders only to specify the destination.
+ this->dest_addr_->set (get_opts.opt_arg ());
+ break;
+ case 'p': // protocol.
+ if (ACE_OS::strcasecmp (get_opts.opt_arg (), ACE_TEXT("tcp")) == 0)
+ this->protocol_ = IPPROTO_TCP;
+ else
+ if (ACE_OS::strcasecmp (get_opts.opt_arg (), ACE_TEXT("udp")) == 0)
+ this->protocol_ = IPPROTO_UDP;
+ else
+ ACE_DEBUG ((LM_DEBUG,
+ "Unknown protocol specified\n"
+ "UDP assumed\n"));
+ break;
+ case 'P': // sender source port.
+ this->source_port_ = ACE_OS::atoi (get_opts.opt_arg ());
+ break;
+ case 'h': // display help for different options.
+ default:
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "usage: %s"
+ " [-m host:port] QoS multicast session address"
+ " Overides the receiver address specified in the -n option"
+ " [-n host:port] Use for a unicast sender. "
+ " Follow by receiver addr"
+ " [-p tcp|udp] specify protocol to be used"
+ " [-P port] source sender port"
+ " [-h] <help>"
+ "\n",
+ argv_ [0]),
+ -1);
+ }
+
+ // If multicast address is specified then ignore the unicast sender
+ // destination address and force the protocol to be UDP.
+ if (this->multicast_flag_ == 1)
+ {
+ this->dest_addr_ = this->mult_session_addr_;
+ this->protocol_ = IPPROTO_UDP;
+ }
+
+ // Indicates successful parsing of command line.
+ return 0;
+}
+
+ACE_INET_Addr *
+QoS_Util::mult_session_addr (void) const
+{
+ return this->mult_session_addr_;
+}
+
+ACE_INET_Addr *
+QoS_Util::dest_addr (void) const
+{
+ return this->dest_addr_;
+}
+
+u_short
+QoS_Util::source_port (void) const
+{
+ return this->source_port_;
+}
+
+ACE_Protocol_ID
+QoS_Util::protocol (void) const
+{
+ return this->protocol_;
+}
+
+int
+QoS_Util::multicast_flag (void) const
+{
+ return this->multicast_flag_;
+}
diff --git a/ACE/examples/QOS/Change_Receiver_FlowSpec/QoS_Util.h b/ACE/examples/QOS/Change_Receiver_FlowSpec/QoS_Util.h
new file mode 100644
index 00000000000..ae347de68f6
--- /dev/null
+++ b/ACE/examples/QOS/Change_Receiver_FlowSpec/QoS_Util.h
@@ -0,0 +1,75 @@
+/* -*- C++ -*- */
+// $Id$
+
+// =====================================================================
+//
+// = LIBRARY
+// ACE_wrappers/examples/QOS
+//
+// = FILENAME
+// QoS_Util.h
+//
+// = AUTHOR
+// Vishal Kachroo <vishal@cs.wustl.edu>
+//
+// =====================================================================
+
+#ifndef QOS_UTIL_H
+#define QOS_UTIL_H
+
+#include "ace/INET_Addr.h"
+#include "ace/QoS/QoS_Session.h"
+
+class QoS_Util
+{
+ // = TITLE
+ // This class provides the utility functions like parse_args ()
+ // required by a QoS enabled application.
+
+public:
+
+ // constructor.
+ QoS_Util (int argc, ACE_TCHAR *argv[]);
+
+ // destructor.
+ ~QoS_Util (void);
+
+ // Parse command-line arguments.
+ int parse_args (void);
+
+ // GET methods.
+ ACE_INET_Addr *mult_session_addr (void) const;
+
+ ACE_INET_Addr *dest_addr (void) const;
+
+ u_short source_port (void) const;
+
+ ACE_Protocol_ID protocol (void) const;
+
+ int multicast_flag (void) const;
+
+private:
+
+ // Command line arguments.
+ int argc_;
+ ACE_TCHAR **argv_;
+
+ // Multicast session address.
+ ACE_INET_Addr *mult_session_addr_;
+
+ // Unicast destination address of the receiver.
+ ACE_INET_Addr *dest_addr_;
+
+ // Source port for the sender.
+ u_short source_port_;
+
+ // Protocol.
+ ACE_Protocol_ID protocol_;
+
+ // Multicast Flag.
+ int multicast_flag_;
+
+};
+
+#endif /* QOS_UTIL_H */
+
diff --git a/ACE/examples/QOS/Change_Receiver_FlowSpec/README b/ACE/examples/QOS/Change_Receiver_FlowSpec/README
new file mode 100644
index 00000000000..58320ef8def
--- /dev/null
+++ b/ACE/examples/QOS/Change_Receiver_FlowSpec/README
@@ -0,0 +1,127 @@
+$Id$
+
+A Regression test for ACE QoS features.
+---------------------------------------
+
+This test implements a simple Receiver-Sender program that ensures
+Quality of Service (QoS) guarantees on the underlying network before
+transmitting data. The program tests the ACE QoS APIs/features. The
+test works for Winsock2 APIs on Win2K as well as RAPI on Solaris.
+
+In addition it dynamically changes the receiver flow spec which in
+turn changes the RESV messages sent.
+
+
+------------------------------------------------------------------------
+WIN2K :
+
+Build Requirements :
+--------------------
+1. Two Win2K machines.
+2. June98 Platform SDK or later.
+3. Link with ws2_32.lib
+
+The test consists of a server (which is the receiver) and a client
+ (which is the sender).
+
+ The receiver is started first (though it is not mandatory) as :
+
+ server -m merengue.cs.wustl.edu:9091
+
+ -m: specifies the multicast session address that both client and
+ server subscribe to for QoS events.
+
+ -p: Protocol to be used. Could be udp or tcp. Default is udp.
+
+ -P: Sender source port. If not specified, DEFAULT_SOURCE_SENDER_PORT
+ (10001) will be used.
+
+ -h: Displays the help on various options.
+
+The sample Sender is started next as :
+
+ client -m merengue.cs.wustl.edu:9091 -P 10004
+
+ -m: specifies the multicast session address that both client and
+ server subscribe to for QoS events.
+
+ -n: Option to be used by senders only to specify the destination
+ address. This option is overriden if a multicast address is also
+ specified through the -m option.
+
+ -p: Protocol to be used. Could be udp or tcp. Default is udp.
+
+ -P: Sender source port. If not specified, DEFAULT_SOURCE_SENDER_PORT
+ (10001) will be used.
+
+ -h: Displays the help on various options.
+
+On Win2K the user must have administrative access to the machine to
+run this program. It seems to be a pre-requisite to opening QoS
+sockets.
+
+The sender and receiver should be run on different Win2K machines.
+
+The test demonstrates how to GQOS enable an application using the ACE QoS APIs.
+It concentrates on the use of various ACE QoS APIs and their correctness.
+
+-------------------------------------------------------------------------------
+
+RAPI :
+
+0. The $ACE_ROOT/include/makeinclude/platform_macros.GNU should be the
+following :
+
+include /project/doc/vishal/ACE_wrappers/include/makeinclude/platform_sunos5_sunc++.GNU
+PLATFORM_RAPI_CPPFLAGS += -I/project/doc/vishal/rapi/rel4.2a4/rsvpd/
+PLATFORM_RAPI_LIBS += -lrsvp
+PLATFORM_RAPI_LDFLAGS += -L/project/doc/vishal/rapi/rel4.2a4/rsvpd/
+
+assuming that RAPI library is installed in /project/doc/vishal/rapi/rel4.2a4/
+
+1. Compile ACE with
+
+ make rapi=1 static_libs_only=1
+
+ Static library option is used because the RAPI library that we have
+ does not compile as a shared object.
+
+2. Run the RSVP Daemon on two machines: (merengue.cs and macarena.cs)
+
+ /project/doc/vishal/rapi/rel4.2a4/rsvpd/rsvpd -D
+
+ The current version of the daemon comes with an inbuilt rtap
+ application to test the various reservation commands and RAPI APIs.
+
+ Typical values for rtap would be :
+
+ sender merengue/5000 [ t 2000000 100000 2000000 512 1024 ]
+ reserve wf [ cl 4000000 200000 4000000 256 2024 ]
+
+
+
+ From ACE:
+ dest udp macarena/5000
+ sender ace/5000 [ t 2000000 100000 2000000 512 1024 ]
+ sender macarena/5022 [ t 2000000 100000 2000000 512 1024 ]
+ sender beguine/6000 [ t 2000000 100000 2000000 512 1024 ]
+
+ From Macarena:
+ wait until done with ACE
+ dest udp macarena/5000 <session name>
+ reserve wf [ cl 2000000 100000 2000000 512 1024 ]
+
+
+
+3. If RTAP runs fine and the daemons show the debug messages about
+ RESV, PATH and other RSVP messages, run the QoS example, making sure
+ that rtap session is released on both machines.
+
+-------------------------------------------------------------------------------
+
+If you run into any problems with this test please contact Vishal
+Kachroo <vishal@cs.wustl.edu>.
+
+This README last updated on 20th July, 2000.
+
+-------------------------------------------------------------------------------
diff --git a/ACE/examples/QOS/Change_Receiver_FlowSpec/Receiver_QoS_Event_Handler.cpp b/ACE/examples/QOS/Change_Receiver_FlowSpec/Receiver_QoS_Event_Handler.cpp
new file mode 100644
index 00000000000..33176ba4da3
--- /dev/null
+++ b/ACE/examples/QOS/Change_Receiver_FlowSpec/Receiver_QoS_Event_Handler.cpp
@@ -0,0 +1,216 @@
+/* -*- C++ -*- */
+// $Id$
+
+// ============================================================================
+//
+// = LIBRARY
+// ACE_wrappers/examples/QOS
+//
+// = FILENAME
+// Receiver_QoS_Event_Handler.cpp
+//
+// = AUTHOR
+// Vishal Kachroo <vishal@cs.wustl.edu>
+//
+// ============================================================================
+
+#include "Receiver_QoS_Event_Handler.h"
+#include "ace/Log_Msg.h"
+#include "ace/SString.h"
+#include "Fill_ACE_QoS.h"
+
+// Constructor.
+Receiver_QoS_Event_Handler::Receiver_QoS_Event_Handler (void)
+{
+}
+
+Receiver_QoS_Event_Handler::Receiver_QoS_Event_Handler (const ACE_SOCK_Dgram_Mcast_QoS
+ &dgram_mcast_qos,
+ ACE_QoS_Session *qos_session)
+ : dgram_mcast_qos_ (dgram_mcast_qos),
+ qos_session_ (qos_session)
+{
+}
+
+// Destructor.
+Receiver_QoS_Event_Handler::~Receiver_QoS_Event_Handler (void)
+{
+}
+
+// Return the handle of the Dgram_Mcast. This method is called
+// internally by the reactor.
+ACE_HANDLE
+Receiver_QoS_Event_Handler::get_handle (void) const
+{
+ return this->dgram_mcast_qos_.get_handle ();
+}
+
+// Called when there is a READ activity on the dgram_mcast_qos handle.
+int
+Receiver_QoS_Event_Handler::handle_input (ACE_HANDLE)
+{
+ char buf[BUFSIZ];
+
+ iovec iov;
+ iov.iov_base = buf;
+ iov.iov_len = BUFSIZ;
+
+ ACE_OS::memset (iov.iov_base,
+ 0,
+ BUFSIZ);
+
+ ACE_DEBUG ((LM_DEBUG,
+ "Inside handle_input () of Receiver_QoS_Event_Handler ()\n"));
+
+ // Receive message from multicast group.
+ ssize_t result =
+ this->dgram_mcast_qos_.recv (&iov,
+ 1,
+ this->remote_addr_);
+
+ if (result != -1)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ "Message Received : %s",
+ iov.iov_base));
+ return 0;
+ }
+ else
+ return -1;
+}
+
+// Called when there is a QoS Event.
+int
+Receiver_QoS_Event_Handler::handle_qos (ACE_HANDLE fd)
+{
+ ACE_UNUSED_ARG (fd);
+
+ ACE_DEBUG ((LM_DEBUG,
+ "\nReceived a QOS event. Inside handle_qos ()\n"));
+
+ // We have received an RSVP event. The following update_qos () call
+ // calls rapi_dispatch () in case of RAPI and WSAIoctl (GET_QOS) in
+ // case of W2K. It then does the QoS parameter translation and updates
+ // the QoS session object with the latest QoS. This call replaces the
+ // direct call that was being made to WSAIoctl (GET_QOS) here for the
+ // Win2K example.
+
+ if (this->qos_session_->update_qos () == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Error in updating QoS\n"),
+ -1);
+ else
+ ACE_DEBUG ((LM_DEBUG,
+ " Updating QOS succeeds.\n"));
+
+ // Now proactively query the QoS object for QoS.
+ ACE_QoS ace_get_qos = this->qos_session_->qos ();
+
+ ACE_DEBUG ((LM_DEBUG,
+ "\nReceiving Flowspec :\t\t\tSending Flowspec :\n\n"
+ "\tToken Rate = %d\t\t\tToken Rate = %d\n"
+ "\tToken Bucket Size = %d\t\t\tToken Bucket Size = %d\n"
+ "\tPeak Bandwidth = %d\t\t\tPeak Bandwidth = %d\n"
+ "\tLatency = %d\t\t\t\tLatency = %d\n"
+ "\tDelay Variation = %d\t\t\tDelay Variation = %d\n"
+ "\tService Type = %d\t\t\tService Type = %d\n"
+ "\tMax SDU Size = %d\t\t\tMax SDU Size = %d\n"
+ "\tMinimum Policed Size = %d\t\tMinimum Policed Size = %d\n\n",
+ ace_get_qos.receiving_flowspec ()->token_rate (),
+ ace_get_qos.sending_flowspec ()->token_rate (),
+ ace_get_qos.receiving_flowspec ()->token_bucket_size (),
+ ace_get_qos.sending_flowspec ()->token_bucket_size (),
+ ace_get_qos.receiving_flowspec ()->peak_bandwidth (),
+ ace_get_qos.sending_flowspec ()->peak_bandwidth (),
+ ace_get_qos.receiving_flowspec ()->latency (),
+ ace_get_qos.sending_flowspec ()->latency (),
+ ace_get_qos.receiving_flowspec ()->delay_variation (),
+ ace_get_qos.sending_flowspec ()->delay_variation (),
+ ace_get_qos.receiving_flowspec ()->service_type (),
+ ace_get_qos.sending_flowspec ()->service_type (),
+ ace_get_qos.receiving_flowspec ()->max_sdu_size (),
+ ace_get_qos.sending_flowspec ()->max_sdu_size (),
+ ace_get_qos.receiving_flowspec ()->minimum_policed_size (),
+ ace_get_qos.sending_flowspec ()->minimum_policed_size ()));
+
+
+ //
+ // create a dynamic flow spec on each callback to test QoS retransmits
+ //
+ ACE_CString flow_id ("flow_id");
+
+ Fill_ACE_QoS flow_spec_list;
+ ACE_DEBUG ((LM_DEBUG,
+ "\nA new flow spec! in QoS handler."));
+
+ static int token_rate = 9400;
+ ++token_rate;
+ static int peak_bw = 18500;
+ ++peak_bw;
+ switch (flow_spec_list.map ().bind (flow_id,
+ new ACE_Flow_Spec (token_rate,
+ 708,
+ peak_bw,
+ 0,
+ 0,
+ ACE_SERVICETYPE_CONTROLLEDLOAD,
+ 368,
+ 368,
+ 25,
+ 1)))
+ {
+ case 1 :
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Unable to bind the new flow spec\n"
+ "The Flow Spec name already exists\n"),
+ -1);
+ break;
+ case -1 :
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Unable to bind the new flow spec\n"),
+ -1);
+ break;
+ }
+
+ //
+ // set up the new qos
+ //
+ ACE_QoS another_qos_receiver;
+ if (flow_spec_list.fill_simplex_receiver_qos (another_qos_receiver,
+ flow_id) !=0)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Unable to fill handler-simplex receiver qos\n"),
+ -1);
+ else
+ ACE_DEBUG ((LM_DEBUG,
+ "Successfully built a new flowspec in handle_qos!\n"));
+
+ //
+ // change the qos for the current session
+ //
+ ACE_QoS_Manager qos_manager = this->dgram_mcast_qos_.qos_manager ();
+
+ ACE_DEBUG ((LM_DEBUG,
+ "QoS Manager was built in handle_qos!\n"));
+
+ // Set the QoS for the session. Replaces the ioctl () call that
+ // was being made previously.
+ if (this->qos_session_->qos (&this->dgram_mcast_qos_,
+ &qos_manager,
+ another_qos_receiver) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Unable to set QoS\n"),
+ -1);
+ else
+ ACE_DEBUG ((LM_DEBUG,
+ "Setting QOS succeeds.\n"));
+
+return 0;
+
+}
+
+
+
+
+
+
diff --git a/ACE/examples/QOS/Change_Receiver_FlowSpec/Receiver_QoS_Event_Handler.h b/ACE/examples/QOS/Change_Receiver_FlowSpec/Receiver_QoS_Event_Handler.h
new file mode 100644
index 00000000000..874d628e3c1
--- /dev/null
+++ b/ACE/examples/QOS/Change_Receiver_FlowSpec/Receiver_QoS_Event_Handler.h
@@ -0,0 +1,61 @@
+/* -*- C++ -*- */
+// $Id$
+
+// ============================================================================
+//
+// = LIBRARY
+// ACE_wrappers/examples/QOS
+//
+// = FILENAME
+// Receiver_QoS_Event_Handler.h
+//
+// = AUTHOR
+// Vishal Kachroo <vishal@cs.wustl.edu>
+//
+// ============================================================================
+
+#ifndef RECEIVER_QOS_EVENT_HANDLER_H
+#define RECEIVER_QOS_EVENT_HANDLER_H
+
+#include "ace/Reactor.h"
+#include "ace/INET_Addr.h"
+#include "ace/Event_Handler.h"
+#include "ace/QoS/QoS_Session.h"
+#include "ace/QoS/SOCK_Dgram_Mcast_QoS.h"
+
+ACE_RCSID(Receiver_QoS_Event_Handler, Receiver_QoS_Event_Handler, "$Id$")
+
+ class Receiver_QoS_Event_Handler : public ACE_Event_Handler
+ {
+ public:
+ // = Initialization and Termination methods.
+ Receiver_QoS_Event_Handler (void);
+ // Constructor.
+
+ Receiver_QoS_Event_Handler::Receiver_QoS_Event_Handler (const ACE_SOCK_Dgram_Mcast_QoS &dgram_mcast_qos,
+ ACE_QoS_Session *qos_session);
+ // Constructor.
+
+ ~Receiver_QoS_Event_Handler (void);
+ // Destructor.
+
+ virtual ACE_HANDLE get_handle (void) const;
+ // Override this to return the handle of the Dgram_Mcast
+ // that we are using.
+
+ virtual int handle_input (ACE_HANDLE fd);
+ // Handles a READ event.
+
+ virtual int handle_qos (ACE_HANDLE fd);
+ // Handles a QoS event.
+
+ private:
+ ACE_SOCK_Dgram_Mcast_QoS dgram_mcast_qos_;
+ ACE_QoS_Session *qos_session_;
+ ACE_INET_Addr remote_addr_;
+ };
+
+#endif /* RECEIVER_QOS_EVENT_HANDLER_H */
+
+
+
diff --git a/ACE/examples/QOS/Change_Receiver_FlowSpec/Sender_QoS_Event_Handler.cpp b/ACE/examples/QOS/Change_Receiver_FlowSpec/Sender_QoS_Event_Handler.cpp
new file mode 100644
index 00000000000..561746a3641
--- /dev/null
+++ b/ACE/examples/QOS/Change_Receiver_FlowSpec/Sender_QoS_Event_Handler.cpp
@@ -0,0 +1,146 @@
+/* -*- C++ -*- */
+// $Id$
+
+// ============================================================================
+//
+// = LIBRARY
+// ACE_wrappers/examples/QOS
+//
+// = FILENAME
+// Sender_QoS_Event_Handler.cpp
+//
+// = AUTHOR
+// Vishal Kachroo <vishal@cs.wustl.edu>
+//
+// ============================================================================
+
+#include "Sender_QoS_Event_Handler.h"
+#include "ace/Log_Msg.h"
+
+#include "Fill_ACE_QoS.h"
+
+// Constructor.
+Sender_QoS_Event_Handler::Sender_QoS_Event_Handler (void)
+{
+}
+
+// Constructor.
+Sender_QoS_Event_Handler::Sender_QoS_Event_Handler (const ACE_SOCK_Dgram_Mcast_QoS
+ &dgram_mcast_qos,
+ ACE_QoS_Session *qos_session)
+ : dgram_mcast_qos_ (dgram_mcast_qos),
+ qos_session_ (qos_session)
+{
+}
+
+// Destructor.
+Sender_QoS_Event_Handler::~Sender_QoS_Event_Handler (void)
+{
+}
+
+// Return the handle of the Dgram_Mcast. This method is called
+// internally by the reactor.
+
+ACE_HANDLE
+Sender_QoS_Event_Handler::get_handle (void) const
+{
+ return this->dgram_mcast_qos_.get_handle ();
+}
+
+// Handle the QoS Event. In this case send data to the receiver
+// using WSASendTo() that uses overlapped I/O.
+
+int
+Sender_QoS_Event_Handler::handle_qos (ACE_HANDLE)
+{
+ ACE_DEBUG ((LM_DEBUG,
+ "\nReceived a QOS event. Inside handle_qos ()\n"));
+
+ // We have received an RSVP event. The following update_qos () call
+ // calls rapi_dispatch () in case of RAPI and WSAIoctl (GET_QOS) in
+ // case of W2K. It then does the QoS parameter translation and updates
+ // the QoS session object with the latest QoS. This call replaces the
+ // direct call that was being made to WSAIoctl (GET_QOS) here for the
+ // Win2K example.
+
+ if (this->qos_session_->update_qos () == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Error in updating QoS\n"),
+ -1);
+ else
+ ACE_DEBUG ((LM_DEBUG,
+ " Updating QOS succeeds.\n"));
+
+ // Now proactively query the QoS object for QoS.
+ ACE_QoS ace_get_qos = this->qos_session_->qos ();
+
+ ACE_DEBUG ((LM_DEBUG,
+ "\nReceiving Flowspec :\t\t\tSending Flowspec :\n\n"
+ "\tToken Rate = %d\t\t\tToken Rate = %d\n"
+ "\tToken Bucket Size = %d\t\t\tToken Bucket Size = %d\n"
+ "\tPeak Bandwidth = %d\t\t\tPeak Bandwidth = %d\n"
+ "\tLatency = %d\t\t\t\tLatency = %d\n"
+ "\tDelay Variation = %d\t\t\tDelay Variation = %d\n"
+ "\tService Type = %d\t\t\tService Type = %d\n"
+ "\tMax SDU Size = %d\t\t\tMax SDU Size = %d\n"
+ "\tMinimum Policed Size = %d\t\tMinimum Policed Size = %d\n\n",
+ ace_get_qos.receiving_flowspec ()->token_rate (),
+ ace_get_qos.sending_flowspec ()->token_rate (),
+ ace_get_qos.receiving_flowspec ()->token_bucket_size (),
+ ace_get_qos.sending_flowspec ()->token_bucket_size (),
+ ace_get_qos.receiving_flowspec ()->peak_bandwidth (),
+ ace_get_qos.sending_flowspec ()->peak_bandwidth (),
+ ace_get_qos.receiving_flowspec ()->latency (),
+ ace_get_qos.sending_flowspec ()->latency (),
+ ace_get_qos.receiving_flowspec ()->delay_variation (),
+ ace_get_qos.sending_flowspec ()->delay_variation (),
+ ace_get_qos.receiving_flowspec ()->service_type (),
+ ace_get_qos.sending_flowspec ()->service_type (),
+ ace_get_qos.receiving_flowspec ()->max_sdu_size (),
+ ace_get_qos.sending_flowspec ()->max_sdu_size (),
+ ace_get_qos.receiving_flowspec ()->minimum_policed_size (),
+ ace_get_qos.sending_flowspec ()->minimum_policed_size ()));
+
+ // This is SPECIFIC TO WIN2K and should be done in the qos_update function.
+
+// ACE_QoS ace_get_qos;
+// u_long dwBytes;
+
+// if (ACE_OS::ioctl (this->dgram_mcast_qos_.get_handle (),
+// ACE_SIO_GET_QOS,
+// ace_get_qos,
+// &dwBytes) == -1)
+// ACE_ERROR ((LM_ERROR,
+// "Error in Qos get ACE_OS::ioctl ()\n"
+// "Bytes Returned = %d\n",
+// dwBytes));
+// else
+// ACE_DEBUG ((LM_DEBUG,
+// "Getting QOS using ACE_OS::ioctl () succeeds.\n"));
+
+ char* msg = "Hello sent on a QoS enabled session !!\n";
+ iovec iov[1];
+ iov[0].iov_base = msg;
+ iov[0].iov_len = ACE_OS::strlen(msg);
+
+ size_t bytes_sent = 0;
+
+ // Send "Hello" to the QoS session address to which the receiver has
+ // subscribed.
+ if (this->dgram_mcast_qos_.send (iov,
+ 1,
+ bytes_sent,
+ 0,
+ this->qos_session_->dest_addr (),
+ 0,
+ 0) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Error in dgram_mcast.send ()\n"),
+ -1);
+ else
+ ACE_DEBUG ((LM_DEBUG,
+ "Using ACE_OS::sendto () : Bytes sent : %d",
+ bytes_sent));
+
+ return 0;
+}
diff --git a/ACE/examples/QOS/Change_Receiver_FlowSpec/Sender_QoS_Event_Handler.h b/ACE/examples/QOS/Change_Receiver_FlowSpec/Sender_QoS_Event_Handler.h
new file mode 100644
index 00000000000..b691bbd0615
--- /dev/null
+++ b/ACE/examples/QOS/Change_Receiver_FlowSpec/Sender_QoS_Event_Handler.h
@@ -0,0 +1,61 @@
+/* -*- C++ -*- */
+// $Id$
+
+// ============================================================================
+//
+// = LIBRARY
+// ACE_wrappers/examples/QOS
+//
+// = FILENAME
+// Sender_QoS_Event_Handler.h
+//
+// = AUTHOR
+// Vishal Kachroo <vishal@cs.wustl.edu>
+//
+// ============================================================================
+
+#ifndef SENDER_QOS_EVENT_HANDLER_H
+#define SENDER_QOS_EVENT_HANDLER_H
+
+#include "ace/Event_Handler.h"
+#include "ace/Reactor.h"
+#include "ace/INET_Addr.h"
+#include "ace/QoS/SOCK_Dgram_Mcast_QoS.h"
+#include "ace/QoS/QoS_Session.h"
+
+//#define MY_DEFPORT 5001
+//#define DEFAULT_MULTICASTGROUP "234.5.6.7"
+
+ACE_RCSID(Sender_QoS_Event_Handler, Sender_QoS_Event_Handler, "$Id$")
+
+class Sender_QoS_Event_Handler : public ACE_Event_Handler
+{
+public:
+ // = Initialization and Termination methods.
+ Sender_QoS_Event_Handler (void);
+ // Constructor.
+
+ Sender_QoS_Event_Handler::Sender_QoS_Event_Handler (const ACE_SOCK_Dgram_Mcast_QoS
+ &dgram_mcast_qos,
+ ACE_QoS_Session *qos_session
+ );
+ // Constructor.
+
+ ~Sender_QoS_Event_Handler (void);
+ // Destructor.
+
+ virtual ACE_HANDLE get_handle (void) const;
+ // Override this to return the handle of the Dgram_Mcast
+ // that we are using.
+
+ virtual int handle_qos (ACE_HANDLE fd);
+ // Handles a QoS event. Right now, just
+ // prints a message.
+
+private:
+
+ ACE_SOCK_Dgram_Mcast_QoS dgram_mcast_qos_;
+ ACE_QoS_Session *qos_session_;
+};
+
+#endif /* SENDER_QOS_EVENT_HANDLER_H */
diff --git a/ACE/examples/QOS/Change_Receiver_FlowSpec/receiver.cpp b/ACE/examples/QOS/Change_Receiver_FlowSpec/receiver.cpp
new file mode 100644
index 00000000000..8ef43514e9b
--- /dev/null
+++ b/ACE/examples/QOS/Change_Receiver_FlowSpec/receiver.cpp
@@ -0,0 +1,300 @@
+/* -*- C++ -*- */
+// $Id$
+
+// ============================================================================
+//
+// = LIBRARY
+// ACE_wrappers/examples/QOS
+//
+// = FILENAME
+// server.cpp
+//
+// = AUTHOR
+// Vishal Kachroo <vishal@cs.wustl.edu>
+//
+// ============================================================================
+
+#define QOSEVENT_MAIN
+
+#include "ace/QoS/QoS_Session.h"
+#include "ace/QoS/QoS_Session_Factory.h"
+#include "ace/QoS/QoS_Decorator.h"
+#include "ace/QoS/SOCK_Dgram_Mcast_QoS.h"
+
+#include "QoS_Util.h"
+#include "Fill_ACE_QoS.h"
+#include "QoS_Signal_Handler.h"
+#include "Receiver_QoS_Event_Handler.h"
+
+// To open QOS sockets administrative access is required on the
+// machine. Fill in default values for QoS structure. The default
+// values were simply choosen from existing QOS templates available
+// via WSAGetQosByName. Notice that ProviderSpecific settings are
+// being allowed when picking the "default" template but not for
+// "well-known" QOS templates. Also notice that since data is only
+// flowing from sender to receiver, different flowspecs are filled in
+// depending upon whether this application is acting as a sender or
+// receiver.
+
+
+// This function fills up the ACE_QoS_Params with the supplied iovec
+// and ACE_QoS.
+
+int
+FillQoSParams (ACE_QoS_Params &qos_params,
+ iovec* iov,
+ ACE_QoS* qos)
+{
+ qos_params.callee_data (iov);
+ qos_params.caller_data (0);
+ qos_params.socket_qos (qos);
+ qos_params.group_socket_qos (0);
+ qos_params.flags (ACE_JL_BOTH);
+
+ return 0;
+}
+
+int
+ACE_TMAIN (int argc, ACE_TCHAR * argv[])
+{
+
+ QoS_Util qos_util(argc, argv);
+
+ if (qos_util.parse_args () == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Error in parsing args\n"),
+ -1);
+
+ // This is a multicast application.
+ if (qos_util.multicast_flag ())
+ {
+ Fill_ACE_QoS fill_ace_qos;
+
+ // The application adds the flow specs that it wants into the
+ // Fill_ACE_QoS. The Fill_ACE_QoS indexes the flow specs by the
+ // flow spec names. Here the new flowspec being added is g_711.
+ ACE_CString g_711 ("g_711");
+
+ switch (fill_ace_qos.map ().bind (g_711,
+ new ACE_Flow_Spec (9200,
+ 708,
+ 18400,
+ 0,
+ 0,
+ ACE_SERVICETYPE_CONTROLLEDLOAD,
+ 368,
+ 368,
+ 25,
+ 1)))
+ {
+ case 1 :
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Unable to bind the new flow spec\n"
+ "The Flow Spec name already exists\n"),
+ -1);
+ break;
+ case -1 :
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Unable to bind the new flow spec\n"),
+ -1);
+ break;
+ }
+
+ ACE_DEBUG ((LM_DEBUG,
+ "g_711 Flow Spec bound successfully\n"));
+
+ // This is a receiver. So we fill in the receiving QoS parameters.
+ ACE_QoS ace_qos_receiver;
+ if (fill_ace_qos.fill_simplex_receiver_qos (ace_qos_receiver,
+ g_711) !=0)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Unable to fill simplex receiver qos\n"),
+ -1);
+ else
+ ACE_DEBUG ((LM_DEBUG,
+ "Filled up the Receiver QoS parameters\n"));
+
+ // Opening a new Multicast Datagram.
+ ACE_SOCK_Dgram_Mcast_QoS dgram_mcast_qos;
+
+ // Multicast Session Address specified by user at command line.
+ // If this address is not specified,
+ // <localhost:ACE_DEFAULT_MULTICAST_PORT> is assumed.
+ ACE_INET_Addr mult_addr (*(qos_util.mult_session_addr ()));
+
+ // Fill the ACE_QoS_Params to be passed to the <ACE_OS::join_leaf>
+ // through subscribe.
+
+ ACE_QoS_Params qos_params;
+ FillQoSParams (qos_params, 0, &ace_qos_receiver);
+
+ // Create a QoS Session Factory.
+ ACE_QoS_Session_Factory session_factory;
+
+ // Ask the factory to create a QoS session.
+ ACE_QoS_Session *qos_session =
+ session_factory.create_session ();
+
+ // Create a destination address for the QoS session. The same
+ // address should be used for the subscribe call later. A copy
+ // is made below only to distinguish the two usages of the dest
+ // address.
+
+ ACE_INET_Addr dest_addr (mult_addr);
+
+ // A QoS session is defined by the 3-tuple [DestAddr, DestPort,
+ // Protocol]. Initialize the QoS session.
+ if (qos_session->open (mult_addr,
+ IPPROTO_UDP) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Error in opening the QoS session\n"),
+ -1);
+ else
+ ACE_DEBUG ((LM_DEBUG,
+ "QoS session opened successfully\n"));
+
+ // The following call opens the Dgram_Mcast and calls the
+ // <ACE_OS::join_leaf> with the qos_params supplied here. Note
+ // the QoS session object is passed into this call. This
+ // subscribes the underlying socket to the passed in QoS
+ // session. For joining multiple multicast sessions, the
+ // following subscribe call should be made with different
+ // multicast addresses and a new QoS session object should be
+ // passed in for each such call. The QoS session objects can be
+ // created only through the session factory. Care should be
+ // taken that the mult_addr for the subscribe() call matches the
+ // dest_addr of the QoS session object. If this is not done, the
+ // subscribe call will fail. A more abstract version of
+ // subscribe will be added that constrains the various features
+ // of GQoS like different flags etc.
+
+ if (dgram_mcast_qos.subscribe (mult_addr,
+ qos_params,
+ 1,
+ 0,
+ AF_INET,
+ // ACE_FROM_PROTOCOL_INFO,
+ 0,
+ 0, // ACE_Protocol_Info,
+ 0,
+ ACE_OVERLAPPED_SOCKET_FLAG
+ | ACE_FLAG_MULTIPOINT_C_LEAF
+ | ACE_FLAG_MULTIPOINT_D_LEAF,
+ qos_session) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Error in subscribe\n"),
+ -1);
+ else
+ ACE_DEBUG ((LM_DEBUG,
+ "Dgram_Mcast subscribe succeeds \n"));
+
+ int nIP_TTL = 25;
+ char achInBuf [BUFSIZ];
+ u_long dwBytes;
+
+ // Should this be abstracted into QoS objects ?? Doesnt seem to have
+ // to do anything directly with QoS.
+ if (ACE_OS::ioctl (dgram_mcast_qos.get_handle (), // Socket.
+ ACE_SIO_MULTICAST_SCOPE, // IO control code.
+ &nIP_TTL, // In buffer.
+ sizeof (nIP_TTL), // Length of in buffer.
+ achInBuf, // Out buffer.
+ BUFSIZ, // Length of Out buffer.
+ &dwBytes, // bytes returned.
+ 0, // Overlapped.
+ 0) == -1) // Func.
+ ACE_ERROR ((LM_ERROR,
+ "Error in Multicast scope ACE_OS::ioctl() \n"));
+ else
+ ACE_DEBUG ((LM_DEBUG,
+ "Setting TTL with Multicast scope ACE_OS::ioctl call succeeds \n"));
+
+ int bFlag = 0;
+
+ // Should this be abstracted into QoS objects ?? Doesnt seem to have
+ // to do anything directly with QoS.
+ if (ACE_OS::ioctl (dgram_mcast_qos.get_handle (), // Socket.
+ ACE_SIO_MULTIPOINT_LOOPBACK, // IO control code.
+ &bFlag, // In buffer.
+ sizeof (bFlag), // Length of in buffer.
+ achInBuf, // Out buffer.
+ BUFSIZ, // Length of Out buffer.
+ &dwBytes, // bytes returned.
+ 0, // Overlapped.
+ 0) == -1) // Func.
+ ACE_ERROR ((LM_ERROR,
+ "Error in Loopback ACE_OS::ioctl() \n"));
+ else
+ ACE_DEBUG ((LM_DEBUG,
+ "Disable Loopback with ACE_OS::ioctl call succeeds \n"));
+
+ // This is a receiver.
+ qos_session->flags (ACE_QoS_Session::ACE_QOS_RECEIVER);
+
+ ACE_QoS_Manager qos_manager = dgram_mcast_qos.qos_manager ();
+
+ // Set the QoS for the session. Replaces the ioctl () call that
+ // was being made previously.
+ if (qos_session->qos (&dgram_mcast_qos,
+ &qos_manager,
+ ace_qos_receiver) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Unable to set QoS\n"),
+ -1);
+ else
+ ACE_DEBUG ((LM_DEBUG,
+ "Setting QOS succeeds.\n"));
+
+ // Register a signal handler that helps to gracefully close the
+ // open QoS sessions.
+ QoS_Signal_Handler qos_signal_handler (qos_session);
+
+ // Register the usual SIGINT signal handler with the Reactor for
+ // the application to gracefully release the QoS session and
+ // shutdown.
+ if (ACE_Reactor::instance ()->register_handler
+ (SIGINT, &qos_signal_handler) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Error in registering the Signal Handler.\n"),
+ -1);
+
+ // Handler to process QoS and Data events for the reciever.
+ Receiver_QoS_Event_Handler qos_event_handler (dgram_mcast_qos,
+ qos_session);
+
+ // Decorate the above handler with QoS functionality.
+ ACE_QoS_Decorator qos_decorator (&qos_event_handler,
+ qos_session);
+
+ // Initialize the Decorator.
+ if (qos_decorator.init () != 0)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "QoS Decorator init () failed.\n"),
+ -1);
+
+ // Register the decorated Event Handler with the Reactor.
+ if (ACE_Reactor::instance ()->register_handler (&qos_decorator,
+ ACE_Event_Handler::QOS_MASK |
+ ACE_Event_Handler::READ_MASK) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Error in registering the Decorator with the Reactor\n"),
+ -1);
+
+
+ // Start the event loop.
+ ACE_DEBUG ((LM_DEBUG,
+ "Running the Event Loop ... \n"));
+
+ ACE_Reactor::instance ()->run_event_loop ();
+
+ ACE_DEBUG ((LM_DEBUG,
+ "(%P|%t) shutting down server logging daemon\n"));
+ }
+ else
+ ACE_DEBUG ((LM_DEBUG,
+ "Specify a -m option for multicast application\n"));
+ return 0;
+}
+
+
+
diff --git a/ACE/examples/QOS/Change_Receiver_FlowSpec/sender.cpp b/ACE/examples/QOS/Change_Receiver_FlowSpec/sender.cpp
new file mode 100644
index 00000000000..c721aa810c4
--- /dev/null
+++ b/ACE/examples/QOS/Change_Receiver_FlowSpec/sender.cpp
@@ -0,0 +1,316 @@
+/* -*- C++ -*- */
+// $Id$
+
+// ============================================================================
+//
+// = LIBRARY
+// ACE_wrappers/examples/QOS
+//
+// = FILENAME
+// client.cpp
+//
+// = AUTHOR
+// Vishal Kachroo <vishal@cs.wustl.edu>
+//
+// ============================================================================
+
+
+#include "ace/QoS/QoS_Session.h"
+#include "ace/QoS/QoS_Session_Factory.h"
+#include "ace/QoS/QoS_Session_Impl.h"
+#include "ace/QoS/QoS_Decorator.h"
+#include "ace/QoS/SOCK_Dgram_Mcast_QoS.h"
+
+#include "QoS_Util.h"
+#include "Fill_ACE_QoS.h"
+#include "QoS_Signal_Handler.h"
+#include "Sender_QoS_Event_Handler.h"
+
+// To open QOS sockets administrative access is required on the
+// machine. Fill in default values for QoS structure. The default
+// values were simply choosen from existing QOS templates available
+// via WSAGetQosByName. Notice that ProviderSpecific settings are
+// being allowed when picking the "default" template but not for
+// "well-known" QOS templates. Also notice that since data is only
+// flowing from sender to receiver, different flowspecs are filled in
+// depending upon whether this application is acting as a sender or
+// receiver.
+
+// This function fills up the ACE_QoS_Params with the supplied iovec and ACE_QoS.
+
+int
+FillQoSParams (ACE_QoS_Params &qos_params,
+ iovec* iov,
+ ACE_QoS* qos)
+{
+ qos_params.callee_data (iov);
+ qos_params.caller_data (0);
+ qos_params.socket_qos (qos);
+ qos_params.group_socket_qos (0);
+ qos_params.flags (ACE_JL_BOTH);
+
+ return 0;
+}
+
+int
+ACE_TMAIN (int argc, ACE_TCHAR * argv[])
+{
+
+ ACE_DEBUG ((LM_DEBUG,
+ "Sender\n"));
+
+ QoS_Util qos_util(argc, argv);
+
+ if (qos_util.parse_args () == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Error in parsing args\n"),
+ -1);
+
+ // This is a multicast application.
+ if (qos_util.multicast_flag ())
+ {
+ Fill_ACE_QoS fill_ace_qos;
+
+ // The application adds the flow specs that it wants into the
+ // Fill_ACE_QoS. The Fill_ACE_QoS indexes the flow specs by the flow
+ // spec names. Here the new flowspec being added is g_711.
+ ACE_CString g_711 ("g_711");
+
+ switch (fill_ace_qos.map ().bind (g_711,
+ new ACE_Flow_Spec (9200,
+ 708,
+ 18400,
+ 0,
+ 0,
+ ACE_SERVICETYPE_CONTROLLEDLOAD,
+ 368,
+ 368,
+ 25,
+ 1)))
+ {
+ case 1 :
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Unable to bind the new flow spec\n"
+ "The Flow Spec name already exists\n"),
+ -1);
+ break;
+ case -1 :
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Unable to bind the new flow spec\n"),
+ -1);
+ break;
+ }
+
+ ACE_DEBUG ((LM_DEBUG,
+ "g_711 Flow Spec bound successfully\n"));
+
+ // This is a sender. So we fill in the sending QoS parameters.
+ ACE_QoS ace_qos_sender;
+
+ if (fill_ace_qos.fill_simplex_sender_qos (ace_qos_sender,
+ g_711) !=0)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Unable to fill simplex sender qos\n"),
+ -1);
+ else
+ ACE_DEBUG ((LM_DEBUG,
+ "Filled up the Sender QoS parameters\n"));
+
+ // Opening a new Multicast Datagram. It is absolutely necessary that
+ // the sender and the receiver subscribe to the same multicast
+ // addresses to make sure the "multicast sessions" for the two are
+ // the same. This is used to match the RESV<->PATH states.
+ ACE_SOCK_Dgram_Mcast_QoS dgram_mcast_qos;
+
+ // Multicast Session Address specified by user at command line.
+ // If this address is not specified,
+ // <localhost:ACE_DEFAULT_MULTICAST_PORT> is assumed.
+ ACE_INET_Addr mult_addr (*(qos_util.mult_session_addr ()));
+
+ // Fill the ACE_QoS_Params to be passed to the <ACE_OS::join_leaf>
+ // through subscribe.
+
+ ACE_QoS_Params qos_params;
+ FillQoSParams (qos_params, 0, &ace_qos_sender);
+
+ // Create a QoS Session Factory.
+ ACE_QoS_Session_Factory session_factory;
+
+ // Ask the factory to create a QoS session.
+ ACE_QoS_Session *qos_session =
+ session_factory.create_session ();
+
+ // Create a destination address for the QoS session. The same
+ // address should be used for the subscribe call later. A copy is
+ // made below only to distinguish the two usages of the dest
+ // address.
+
+ ACE_INET_Addr dest_addr (mult_addr);
+
+ // A QoS session is defined by the 3-tuple [DestAddr, DestPort,
+ // Protocol]. Initialize the QoS session.
+ if (qos_session->open (mult_addr,
+ IPPROTO_UDP) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Error in opening the QoS session\n"),
+ -1);
+ else
+ ACE_DEBUG ((LM_DEBUG,
+ "QoS session opened successfully\n"));
+
+ // The following call opens the Dgram_Mcast and calls the
+ // <ACE_OS::join_leaf> with the qos_params supplied here. Note the
+ // QoS session object is passed into this call. This subscribes the
+ // underlying socket to the passed in QoS session. For joining
+ // multiple multicast sessions, the following subscribe call should
+ // be made with different multicast addresses and a new QoS session
+ // object should be passed in for each such call. The QoS session
+ // objects can be created only through the session factory. Care
+ // should be taken that the mult_addr for the subscribe() call
+ // matches the dest_addr of the QoS session object. If this is not
+ // done, the subscribe call will fail. A more abstract version of
+ // subscribe will be added that constrains the various features of
+ // GQoS like different flags etc.
+
+ if (dgram_mcast_qos.subscribe (mult_addr,
+ qos_params,
+ 1,
+ 0,
+ AF_INET,
+ // ACE_FROM_PROTOCOL_INFO,
+ 0,
+ 0, // ACE_Protocol_Info,
+ 0,
+ ACE_OVERLAPPED_SOCKET_FLAG
+ | ACE_FLAG_MULTIPOINT_C_LEAF
+ | ACE_FLAG_MULTIPOINT_D_LEAF,
+ qos_session) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Error in subscribe\n"),
+ -1);
+ else
+ ACE_DEBUG ((LM_DEBUG,
+ "Dgram_Mcast subscribe succeeds \n"));
+
+ int nIP_TTL = 25;
+ char achInBuf [BUFSIZ];
+ u_long dwBytes;
+
+ // Should this be abstracted into QoS objects ?? Doesnt seem to have
+ // to do anything directly with QoS.
+ if (ACE_OS::ioctl (dgram_mcast_qos.get_handle (), // Socket.
+ ACE_SIO_MULTICAST_SCOPE, // IO control code.
+ &nIP_TTL, // In buffer.
+ sizeof (nIP_TTL), // Length of in buffer.
+ achInBuf, // Out buffer.
+ BUFSIZ, // Length of Out buffer.
+ &dwBytes, // bytes returned.
+ 0, // Overlapped.
+ 0) == -1) // Func.
+ ACE_ERROR ((LM_ERROR,
+ "Error in Multicast scope ACE_OS::ioctl() \n"));
+ else
+ ACE_DEBUG ((LM_DEBUG,
+ "Setting TTL with Multicast scope ACE_OS::ioctl call succeeds \n"));
+
+ int bFlag = 0;
+
+ // Should this be abstracted into QoS objects ?? Doesnt seem to have
+ // to do anything directly with QoS.
+ if (ACE_OS::ioctl (dgram_mcast_qos.get_handle (), // Socket.
+ ACE_SIO_MULTIPOINT_LOOPBACK, // IO control code.
+ &bFlag, // In buffer.
+ sizeof (bFlag), // Length of in buffer.
+ achInBuf, // Out buffer.
+ BUFSIZ, // Length of Out buffer.
+ &dwBytes, // bytes returned.
+ 0, // Overlapped.
+ 0) == -1) // Func.
+ ACE_ERROR ((LM_ERROR,
+ "Error in Loopback ACE_OS::ioctl() \n"));
+ else
+ ACE_DEBUG ((LM_DEBUG,
+ "Disable Loopback with ACE_OS::ioctl call succeeds \n"));
+
+ // This is a sender.
+ qos_session->flags (ACE_QoS_Session::ACE_QOS_SENDER);
+
+ ACE_QoS_Manager qos_manager = dgram_mcast_qos.qos_manager ();
+
+ // Since we are using RSVP, it is imperative that the client
+ // application have the option of supplying the source sender
+ // port for the RSVP messages. A default will be chosen by the
+ // ACE API if this is not done.
+ qos_session->source_port (qos_util.source_port ());
+
+ // Set the QoS for the session. Replaces the ioctl () call that
+ // was being made previously.
+ if (qos_session->qos (&dgram_mcast_qos,
+ &qos_manager,
+ ace_qos_sender) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Unable to set QoS\n"),
+ -1);
+ else
+ ACE_DEBUG ((LM_DEBUG,
+ "Setting QOS succeeds.\n"));
+
+ // Register a signal handler that helps to gracefully close the open
+ // QoS sessions.
+ QoS_Signal_Handler qos_signal_handler (qos_session);
+
+ // Register the usual SIGINT signal handler with the Reactor for
+ // the application to gracefully release the QoS session and
+ // shutdown.
+ if (ACE_Reactor::instance ()->register_handler
+ (SIGINT, &qos_signal_handler) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Error in registering the Signal Handler.\n"),
+ -1);
+
+ // Handler to process QoS and Data events for the reciever.
+ Sender_QoS_Event_Handler qos_event_handler (dgram_mcast_qos,
+ qos_session);
+
+ // Decorate the above handler with QoS functionality.
+ ACE_QoS_Decorator qos_decorator (&qos_event_handler,
+ qos_session);
+
+ // Initialize the Decorator.
+ if (qos_decorator.init () != 0)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "QoS Decorator init () failed.\n"),
+ -1);
+
+ // Register the decorated Event Handler with the Reactor.
+ if (ACE_Reactor::instance ()->register_handler (&qos_decorator,
+ ACE_Event_Handler::QOS_MASK |
+ ACE_Event_Handler::READ_MASK) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Error in registering the Decorator with the Reactor\n"),
+ -1);
+
+
+
+
+ // Start the event loop.
+ ACE_DEBUG ((LM_DEBUG,
+ "Running the Event Loop ... \n"));
+
+ ACE_Reactor::instance ()->run_event_loop ();
+
+ ACE_DEBUG ((LM_DEBUG,
+ "(%P|%t) shutting down server logging daemon\n"));
+ }
+ else
+ ACE_DEBUG ((LM_DEBUG,
+ "Specify a -m option for multicast application\n"));
+ return 0;
+}
+
+
+
+
+
+
+
diff --git a/ACE/examples/QOS/Change_Sender_TSpec/Fill_ACE_QoS.cpp b/ACE/examples/QOS/Change_Sender_TSpec/Fill_ACE_QoS.cpp
new file mode 100644
index 00000000000..20c03f40fa6
--- /dev/null
+++ b/ACE/examples/QOS/Change_Sender_TSpec/Fill_ACE_QoS.cpp
@@ -0,0 +1,99 @@
+// Fill_ACE_QoS.cpp
+// $Id$
+
+#include "Fill_ACE_QoS.h"
+
+ACE_RCSID(QOS, Fill_ACE_QoS,"$Id$")
+
+const iovec Fill_ACE_QoS::iov_ = {0,0};
+
+Fill_ACE_QoS::Fill_ACE_QoS (void)
+{
+ ACE_NEW (this->default_traffic_,
+ ACE_Flow_Spec (ACE_QOS_NOT_SPECIFIED,
+ ACE_QOS_NOT_SPECIFIED,
+ ACE_QOS_NOT_SPECIFIED,
+ ACE_QOS_NOT_SPECIFIED,
+ ACE_QOS_NOT_SPECIFIED,
+ ACE_SERVICETYPE_NOTRAFFIC,
+ ACE_QOS_NOT_SPECIFIED,
+ ACE_QOS_NOT_SPECIFIED,
+ 25,
+ 1));
+}
+
+// destructor.
+Fill_ACE_QoS::~Fill_ACE_QoS (void)
+{}
+
+int
+Fill_ACE_QoS::fill_simplex_receiver_qos (ACE_QoS &ace_qos,
+ const ACE_CString &recv_flow_name)
+{
+ ACE_Flow_Spec *recv_flow_spec = 0;
+
+ if (this->map ().find (recv_flow_name, recv_flow_spec) != 0)
+ ACE_ERROR_RETURN ((LM_DEBUG,
+ "Unable to find a FlowSpec with name %s",
+ recv_flow_name.c_str ()),
+ -1);
+ ace_qos.receiving_flowspec (recv_flow_spec);
+ ace_qos.sending_flowspec ((this->default_traffic_));
+ ace_qos.provider_specific (Fill_ACE_QoS::iov_);
+
+ return 0;
+}
+
+
+int
+Fill_ACE_QoS::fill_simplex_sender_qos (ACE_QoS &ace_qos,
+ const ACE_CString &send_flow_name)
+{
+ ACE_Flow_Spec *send_flow_spec = 0;
+
+ if (this->map ().find (send_flow_name, send_flow_spec) != 0)
+ ACE_ERROR_RETURN ((LM_DEBUG,
+ "Unable to find a FlowSpec with name %s",
+ send_flow_name.c_str ()),
+ -1);
+
+ ace_qos.receiving_flowspec ((this->default_traffic_));
+ ace_qos.sending_flowspec (send_flow_spec);
+ ace_qos.provider_specific (Fill_ACE_QoS::iov_);
+
+ return 0;
+}
+
+int
+Fill_ACE_QoS::fill_duplex_qos (ACE_QoS &ace_qos,
+ const ACE_CString &recv_flow_name,
+ const ACE_CString &send_flow_name)
+{
+ ACE_Flow_Spec *send_flow_spec = 0;
+ ACE_Flow_Spec *recv_flow_spec = 0;
+
+ if (this->map ().find (recv_flow_name, recv_flow_spec) != 0)
+ ACE_ERROR_RETURN ((LM_DEBUG,
+ "Unable to find a FlowSpec with name %s",
+ recv_flow_name.c_str ()),
+ -1);
+
+ if (this->map ().find (send_flow_name, send_flow_spec) != 0)
+ ACE_ERROR_RETURN ((LM_DEBUG,
+ "Unable to find a FlowSpec with name %s",
+ send_flow_name.c_str ()),
+ -1);
+
+ ace_qos.receiving_flowspec (recv_flow_spec);
+ ace_qos.sending_flowspec (send_flow_spec);
+ ace_qos.provider_specific (Fill_ACE_QoS::iov_);
+
+ return 0;
+}
+
+Fill_ACE_QoS::FLOW_SPEC_HASH_MAP&
+Fill_ACE_QoS::map (void)
+{
+ return this->flow_spec_map_;
+}
+
diff --git a/ACE/examples/QOS/Change_Sender_TSpec/Fill_ACE_QoS.h b/ACE/examples/QOS/Change_Sender_TSpec/Fill_ACE_QoS.h
new file mode 100644
index 00000000000..776d713e5e5
--- /dev/null
+++ b/ACE/examples/QOS/Change_Sender_TSpec/Fill_ACE_QoS.h
@@ -0,0 +1,75 @@
+/* -*- C++ -*- */
+// $Id$
+
+// ============================================================================
+//
+// = LIBRARY
+// ACE_wrappers/examples/QOS
+//
+// = FILENAME
+// Fill_ACE_QoS.h
+//
+// = AUTHOR
+// Vishal Kachroo <vishal@cs.wustl.edu>
+//
+// ============================================================================
+
+#ifndef FILL_ACE_QOS_H
+#define FILL_ACE_QOS_H
+
+#include "ace/SString.h"
+#include "ace/Hash_Map_Manager.h"
+#include "ace/Null_Mutex.h"
+#include "ace/ACE.h"
+#include "ace/OS_QoS.h"
+
+class Fill_ACE_QoS
+{
+ // TITLE
+ // This class helps users to add new flow specs and provides
+ // utility functions for filling up the flow specs for simplex/duplex
+ // sessions.
+
+public:
+ typedef ACE_Hash_Map_Manager <ACE_CString, ACE_Flow_Spec *, ACE_Null_Mutex> FLOW_SPEC_HASH_MAP;
+
+ //Initialization and termination methods.
+ Fill_ACE_QoS (void);
+ // constructor.
+
+ ~Fill_ACE_QoS (void);
+ // destructor.
+
+ int fill_simplex_receiver_qos (ACE_QoS &ace_qos,
+ const ACE_CString &recv_flow_name);
+ // To be used by receivers. Fills the receiver qos and sets the
+ // sender qos to NO_TRAFFIC.
+
+ int fill_simplex_sender_qos (ACE_QoS &ace_qos,
+ const ACE_CString &send_flow_name);
+ // To be used by senders. Fills the sender qos and sets the receiver
+ // qos to NO_TRAFFIC.
+
+ int fill_duplex_qos (ACE_QoS &ace_qos,
+ const ACE_CString &recv_flow_name,
+ const ACE_CString &send_flow_name);
+ // To be used by applications that wish to be both receivers and
+ // senders.
+
+ FLOW_SPEC_HASH_MAP& map (void);
+ // Returns the hash map of flowspecs indexed by flowspec name.
+
+private:
+
+ // The Service Provider is currently set to NULL for all ACE_QoS.
+ static const iovec iov_;
+
+ // A NO_TRAFFIC flow spec. Senders set the receiving qos to this
+ // while the receivers set the sending qos to this.
+ ACE_Flow_Spec *default_traffic_;
+
+ // A list of flowspecs indexed by the flowspec name.
+ FLOW_SPEC_HASH_MAP flow_spec_map_;
+};
+
+#endif /* FILL_ACE_QOS_H */
diff --git a/ACE/examples/QOS/Change_Sender_TSpec/FlowSpec_Dbase.h b/ACE/examples/QOS/Change_Sender_TSpec/FlowSpec_Dbase.h
new file mode 100644
index 00000000000..fc382048c13
--- /dev/null
+++ b/ACE/examples/QOS/Change_Sender_TSpec/FlowSpec_Dbase.h
@@ -0,0 +1,52 @@
+/* -*- C++ -*- */
+//$Id$
+
+// ============================================================================
+//
+// = LIBRARY
+// ACE_wrappers/examples/QOS
+//
+// = FILENAME
+// FlowSpec_Dbase.h
+//
+// = AUTHOR
+// Vishal Kachroo <vishal@cs.wustl.edu>
+//
+// ============================================================================
+
+#ifndef FLOWSPEC_DBASE_H
+#define FLOWSPEC_DBASE_H
+
+// This file contains the different FlowSpecs that the QoS enabled
+// application uses. Its a good idea to list them all here so the
+// application code is clean.
+
+ACE_Flow_Spec notraffic (ACE_QOS_NOT_SPECIFIED,
+ ACE_QOS_NOT_SPECIFIED,
+ ACE_QOS_NOT_SPECIFIED,
+ ACE_QOS_NOT_SPECIFIED,
+ ACE_QOS_NOT_SPECIFIED,
+ ACE_SERVICETYPE_NOTRAFFIC,
+ ACE_QOS_NOT_SPECIFIED,
+ ACE_QOS_NOT_SPECIFIED,
+ 25,
+ 1);
+
+ACE_Flow_Spec g711 (9200,
+ 708,
+ 18400,
+ 0,
+ 0,
+ ACE_SERVICETYPE_CONTROLLEDLOAD,
+ 368,
+ 368,
+ 25,
+ 1);
+
+// The default session address is macarena.cs.wustl.edu. I am using macarena
+// as my receiver for testing.
+#define DEFAULT_QOS_SESSION_MACHINE "128.252.165.127"
+#define DEFAULT_QOS_SESSION_PORT 8001
+
+#endif /* FLOWSPEC_DBASE_H */
+
diff --git a/ACE/examples/QOS/Change_Sender_TSpec/Makefile.am b/ACE/examples/QOS/Change_Sender_TSpec/Makefile.am
new file mode 100644
index 00000000000..980d5cf3422
--- /dev/null
+++ b/ACE/examples/QOS/Change_Sender_TSpec/Makefile.am
@@ -0,0 +1,76 @@
+## Process this file with automake to create Makefile.in
+##
+## $Id$
+##
+## This file was generated by MPC. Any changes made directly to
+## this file will be lost the next time it is generated.
+##
+## MPC Command:
+## /acebuilds/ACE_wrappers-repository/bin/mwc.pl -include /acebuilds/MPC/config -include /acebuilds/MPC/templates -feature_file /acebuilds/ACE_wrappers-repository/local.features -noreldefs -type automake -exclude build,Kokyu
+
+ACE_BUILDDIR = $(top_builddir)
+ACE_ROOT = $(top_srcdir)
+
+noinst_PROGRAMS =
+
+## Makefile.QOS_Change_Sender_TSpec_Receiver.am
+
+if BUILD_QOS
+noinst_PROGRAMS += receiver
+
+receiver_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR) \
+ -DACE_HAS_QOS
+
+receiver_SOURCES = \
+ Fill_ACE_QoS.cpp \
+ QoS_Signal_Handler.cpp \
+ QoS_Util.cpp \
+ Receiver_QoS_Event_Handler.cpp \
+ receiver.cpp \
+ Fill_ACE_QoS.h \
+ QoS_Signal_Handler.h \
+ QoS_Util.h \
+ Receiver_QoS_Event_Handler.h
+
+receiver_LDADD = \
+ $(ACE_BUILDDIR)/ace/QoS/libACE_QoS.la \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+endif BUILD_QOS
+
+## Makefile.QOS_Change_Sender_TSpec_Sender.am
+
+if BUILD_QOS
+noinst_PROGRAMS += sender
+
+sender_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR) \
+ -DACE_HAS_QOS
+
+sender_SOURCES = \
+ Fill_ACE_QoS.cpp \
+ QoS_Signal_Handler.cpp \
+ QoS_Util.cpp \
+ Sender_QoS_Event_Handler.cpp \
+ sender.cpp \
+ Fill_ACE_QoS.h \
+ QoS_Signal_Handler.h \
+ QoS_Util.h \
+ Sender_QoS_Event_Handler.h
+
+sender_LDADD = \
+ $(ACE_BUILDDIR)/ace/QoS/libACE_QoS.la \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+endif BUILD_QOS
+
+## Clean up template repositories, etc.
+clean-local:
+ -rm -f *~ *.bak *.rpo *.sym lib*.*_pure_* core core.*
+ -rm -f gcctemp.c gcctemp so_locations *.ics
+ -rm -rf cxx_repository ptrepository ti_files
+ -rm -rf templateregistry ir.out
+ -rm -rf ptrepository SunWS_cache Templates.DB
diff --git a/ACE/examples/QOS/Change_Sender_TSpec/QOS_Change_Sender_TSpec.mpc b/ACE/examples/QOS/Change_Sender_TSpec/QOS_Change_Sender_TSpec.mpc
new file mode 100644
index 00000000000..9767bd6fdb9
--- /dev/null
+++ b/ACE/examples/QOS/Change_Sender_TSpec/QOS_Change_Sender_TSpec.mpc
@@ -0,0 +1,25 @@
+// -*- MPC -*-
+// $Id$
+
+project(*receiver) : aceexe, qos {
+ exename = receiver
+ requires += qos
+ Source_Files {
+ Fill_ACE_QoS.cpp
+ QoS_Signal_Handler.cpp
+ QoS_Util.cpp
+ receiver.cpp
+ Receiver_QoS_Event_Handler.cpp
+ }
+}
+project(*sender) : aceexe, qos {
+ exename = sender
+ requires += qos
+ Source_Files {
+ Fill_ACE_QoS.cpp
+ QoS_Signal_Handler.cpp
+ QoS_Util.cpp
+ sender.cpp
+ Sender_QoS_Event_Handler.cpp
+ }
+}
diff --git a/ACE/examples/QOS/Change_Sender_TSpec/QoS_Signal_Handler.cpp b/ACE/examples/QOS/Change_Sender_TSpec/QoS_Signal_Handler.cpp
new file mode 100644
index 00000000000..9f07ad5b378
--- /dev/null
+++ b/ACE/examples/QOS/Change_Sender_TSpec/QoS_Signal_Handler.cpp
@@ -0,0 +1,34 @@
+// QoS_Signal_Handler.cpp
+// $Id$
+
+#include "ace/Log_Msg.h"
+#include "QoS_Signal_Handler.h"
+
+ACE_RCSID(QOS, QoS_Signal_Handler,"$Id$")
+
+// constructor.
+QoS_Signal_Handler::QoS_Signal_Handler (ACE_QoS_Session *qos_session)
+ : qos_session_ (qos_session)
+{
+}
+
+// Releases the QoS sessions gracefully.
+int
+QoS_Signal_Handler::handle_signal (int signum, siginfo_t *, ucontext_t*)
+{
+ if (signum == SIGINT)
+ {
+ if (this->qos_session_->close () == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Unable to close the QoS session.\n"),
+ -1);
+ else
+ ACE_DEBUG ((LM_DEBUG,
+ "QoS Session with id %d closed successfully.\n",
+ this->qos_session_->session_id ()));
+ }
+ else
+ ACE_DEBUG ((LM_DEBUG,
+ "A signal other than SIGINT received.\nIgnoring.\n"));
+ return 0;
+}
diff --git a/ACE/examples/QOS/Change_Sender_TSpec/QoS_Signal_Handler.h b/ACE/examples/QOS/Change_Sender_TSpec/QoS_Signal_Handler.h
new file mode 100644
index 00000000000..35b9f3a19e7
--- /dev/null
+++ b/ACE/examples/QOS/Change_Sender_TSpec/QoS_Signal_Handler.h
@@ -0,0 +1,45 @@
+/* -*- C++ -*- */
+// $Id$
+
+// =====================================================================
+//
+// = LIBRARY
+// ACE_wrappers/examples/QOS
+//
+// = FILENAME
+// QoS_Signal_Handler.h
+//
+// = AUTHOR
+// Vishal Kachroo <vishal@cs.wustl.edu>
+//
+// =====================================================================
+
+#ifndef QOS_SIGNAL_HANDLER_H
+#define QOS_SIGNAL_HANDLER_H
+
+#include "ace/Event_Handler.h"
+#include "ace/QoS/QoS_Session.h"
+
+class QoS_Signal_Handler : public ACE_Event_Handler
+{
+ // TITLE
+ // This class Handles the SIGINT signal through the Reactor.
+ // Useful to gracefully release QoS sessions.
+
+public:
+
+ QoS_Signal_Handler (ACE_QoS_Session *qos_session);
+ // constructor.
+
+ int handle_signal(int signum, siginfo_t*,ucontext_t*);
+ // Override this method to implement graceful shutdown.
+
+private:
+
+ ACE_QoS_Session *qos_session_;
+ // Session to be gracefully shutdown.
+
+};
+
+#endif /* QOS_SIGNAL_HANDLER_H */
+
diff --git a/ACE/examples/QOS/Change_Sender_TSpec/QoS_Util.cpp b/ACE/examples/QOS/Change_Sender_TSpec/QoS_Util.cpp
new file mode 100644
index 00000000000..0ef3b353248
--- /dev/null
+++ b/ACE/examples/QOS/Change_Sender_TSpec/QoS_Util.cpp
@@ -0,0 +1,122 @@
+// QoS_Session_Impl.cpp
+// $Id$
+
+#define SENDER_PORT 10001
+
+#include "ace/Log_Msg.h"
+#include "ace/Get_Opt.h"
+#include "QoS_Util.h"
+#include "ace/OS_NS_strings.h"
+
+ACE_RCSID(QOS, QoS_Util,"$Id$")
+
+// constructor.
+QoS_Util::QoS_Util (int argc,
+ ACE_TCHAR *argv[])
+ : argc_ (argc),
+ argv_ (argv),
+ source_port_ (SENDER_PORT),
+ protocol_ (IPPROTO_UDP),
+ multicast_flag_ (0)
+{
+ ACE_NEW (this->mult_session_addr_,
+ ACE_INET_Addr (ACE_DEFAULT_MULTICAST_PORT));
+
+ ACE_NEW (this->dest_addr_,
+ ACE_INET_Addr (ACE_DEFAULT_SERVER_PORT));
+}
+
+// destructor.
+QoS_Util::~QoS_Util (void)
+{
+ delete this->mult_session_addr_;
+ delete this->dest_addr_;
+}
+
+int
+QoS_Util::parse_args (void)
+{
+ ACE_Get_Opt get_opts (this->argc_, this->argv_, ACE_TEXT("m:n:p:P:c"));
+ int c = 0;
+
+ while ((c = get_opts ()) != -1)
+ switch (c)
+ {
+ case 'm': // multicast session address.
+ this->multicast_flag_ = 1;
+ this->mult_session_addr_->set (get_opts.opt_arg ());
+ break;
+ case 'n': // to be used by Senders only to specify the destination.
+ this->dest_addr_->set (get_opts.opt_arg ());
+ break;
+ case 'p': // protocol.
+ if (ACE_OS::strcasecmp (get_opts.opt_arg (), ACE_TEXT("tcp")) == 0)
+ this->protocol_ = IPPROTO_TCP;
+ else
+ if (ACE_OS::strcasecmp (get_opts.opt_arg (), ACE_TEXT("udp")) == 0)
+ this->protocol_ = IPPROTO_UDP;
+ else
+ ACE_DEBUG ((LM_DEBUG,
+ "Unknown protocol specified\n"
+ "UDP assumed\n"));
+ break;
+ case 'P': // sender source port.
+ this->source_port_ = ACE_OS::atoi (get_opts.opt_arg ());
+ break;
+ case 'h': // display help for different options.
+ default:
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "usage: %s"
+ " [-m host:port] QoS multicast session address"
+ " Overides the receiver address specified in the -n option"
+ " [-n host:port] Use for a unicast sender. "
+ " Follow by receiver addr"
+ " [-p tcp|udp] specify protocol to be used"
+ " [-P port] source sender port"
+ " [-h] <help>"
+ "\n",
+ argv_ [0]),
+ -1);
+ }
+
+ // If multicast address is specified then ignore the unicast sender
+ // destination address and force the protocol to be UDP.
+ if (this->multicast_flag_ == 1)
+ {
+ this->dest_addr_ = this->mult_session_addr_;
+ this->protocol_ = IPPROTO_UDP;
+ }
+
+ // Indicates successful parsing of command line.
+ return 0;
+}
+
+ACE_INET_Addr *
+QoS_Util::mult_session_addr (void) const
+{
+ return this->mult_session_addr_;
+}
+
+ACE_INET_Addr *
+QoS_Util::dest_addr (void) const
+{
+ return this->dest_addr_;
+}
+
+u_short
+QoS_Util::source_port (void) const
+{
+ return this->source_port_;
+}
+
+ACE_Protocol_ID
+QoS_Util::protocol (void) const
+{
+ return this->protocol_;
+}
+
+int
+QoS_Util::multicast_flag (void) const
+{
+ return this->multicast_flag_;
+}
diff --git a/ACE/examples/QOS/Change_Sender_TSpec/QoS_Util.h b/ACE/examples/QOS/Change_Sender_TSpec/QoS_Util.h
new file mode 100644
index 00000000000..ae347de68f6
--- /dev/null
+++ b/ACE/examples/QOS/Change_Sender_TSpec/QoS_Util.h
@@ -0,0 +1,75 @@
+/* -*- C++ -*- */
+// $Id$
+
+// =====================================================================
+//
+// = LIBRARY
+// ACE_wrappers/examples/QOS
+//
+// = FILENAME
+// QoS_Util.h
+//
+// = AUTHOR
+// Vishal Kachroo <vishal@cs.wustl.edu>
+//
+// =====================================================================
+
+#ifndef QOS_UTIL_H
+#define QOS_UTIL_H
+
+#include "ace/INET_Addr.h"
+#include "ace/QoS/QoS_Session.h"
+
+class QoS_Util
+{
+ // = TITLE
+ // This class provides the utility functions like parse_args ()
+ // required by a QoS enabled application.
+
+public:
+
+ // constructor.
+ QoS_Util (int argc, ACE_TCHAR *argv[]);
+
+ // destructor.
+ ~QoS_Util (void);
+
+ // Parse command-line arguments.
+ int parse_args (void);
+
+ // GET methods.
+ ACE_INET_Addr *mult_session_addr (void) const;
+
+ ACE_INET_Addr *dest_addr (void) const;
+
+ u_short source_port (void) const;
+
+ ACE_Protocol_ID protocol (void) const;
+
+ int multicast_flag (void) const;
+
+private:
+
+ // Command line arguments.
+ int argc_;
+ ACE_TCHAR **argv_;
+
+ // Multicast session address.
+ ACE_INET_Addr *mult_session_addr_;
+
+ // Unicast destination address of the receiver.
+ ACE_INET_Addr *dest_addr_;
+
+ // Source port for the sender.
+ u_short source_port_;
+
+ // Protocol.
+ ACE_Protocol_ID protocol_;
+
+ // Multicast Flag.
+ int multicast_flag_;
+
+};
+
+#endif /* QOS_UTIL_H */
+
diff --git a/ACE/examples/QOS/Change_Sender_TSpec/README b/ACE/examples/QOS/Change_Sender_TSpec/README
new file mode 100644
index 00000000000..a8423774320
--- /dev/null
+++ b/ACE/examples/QOS/Change_Sender_TSpec/README
@@ -0,0 +1,126 @@
+$Id$
+
+A Regression test for ACE QoS features.
+---------------------------------------
+
+This test implements a simple Receiver-Sender program that ensures
+Quality of Service (QoS) guarantees on the underlying network before
+transmitting data. The program tests the ACE QoS APIs/features. The
+test works for Winsock2 APIs on Win2K as well as RAPI on Solaris.
+
+In addition it dynamically changes the sender TSpec which in turn
+changes the PATH messages.
+
+------------------------------------------------------------------------
+WIN2K :
+
+Build Requirements :
+--------------------
+1. Two Win2K machines.
+2. June98 Platform SDK or later.
+3. Link with ws2_32.lib
+
+The test consists of a server (which is the receiver) and a client
+ (which is the sender).
+
+ The receiver is started first (though it is not mandatory) as :
+
+ server -m merengue.cs.wustl.edu:9091
+
+ -m: specifies the multicast session address that both client and
+ server subscribe to for QoS events.
+
+ -p: Protocol to be used. Could be udp or tcp. Default is udp.
+
+ -P: Sender source port. If not specified, DEFAULT_SOURCE_SENDER_PORT
+ (10001) will be used.
+
+ -h: Displays the help on various options.
+
+The sample Sender is started next as :
+
+ client -m merengue.cs.wustl.edu:9091 -P 10004
+
+ -m: specifies the multicast session address that both client and
+ server subscribe to for QoS events.
+
+ -n: Option to be used by senders only to specify the destination
+ address. This option is overriden if a multicast address is also
+ specified through the -m option.
+
+ -p: Protocol to be used. Could be udp or tcp. Default is udp.
+
+ -P: Sender source port. If not specified, DEFAULT_SOURCE_SENDER_PORT
+ (10001) will be used.
+
+ -h: Displays the help on various options.
+
+On Win2K the user must have administrative access to the machine to
+run this program. It seems to be a pre-requisite to opening QoS
+sockets.
+
+The sender and receiver should be run on different Win2K machines.
+
+The test demonstrates how to GQOS enable an application using the ACE QoS APIs.
+It concentrates on the use of various ACE QoS APIs and their correctness.
+
+-------------------------------------------------------------------------------
+
+RAPI :
+
+0. The $ACE_ROOT/include/makeinclude/platform_macros.GNU should be the
+following :
+
+include /project/doc/vishal/ACE_wrappers/include/makeinclude/platform_sunos5_sunc++.GNU
+PLATFORM_RAPI_CPPFLAGS += -I/project/doc/vishal/rapi/rel4.2a4/rsvpd/
+PLATFORM_RAPI_LIBS += -lrsvp
+PLATFORM_RAPI_LDFLAGS += -L/project/doc/vishal/rapi/rel4.2a4/rsvpd/
+
+assuming that RAPI library is installed in /project/doc/vishal/rapi/rel4.2a4/
+
+1. Compile ACE with
+
+ make rapi=1 static_libs_only=1
+
+ Static library option is used because the RAPI library that we have
+ does not compile as a shared object.
+
+2. Run the RSVP Daemon on two machines: (merengue.cs and macarena.cs)
+
+ /project/doc/vishal/rapi/rel4.2a4/rsvpd/rsvpd -D
+
+ The current version of the daemon comes with an inbuilt rtap
+ application to test the various reservation commands and RAPI APIs.
+
+ Typical values for rtap would be :
+
+ sender merengue/5000 [ t 2000000 100000 2000000 512 1024 ]
+ reserve wf [ cl 4000000 200000 4000000 256 2024 ]
+
+
+
+ From ACE:
+ dest udp macarena/5000
+ sender ace/5000 [ t 2000000 100000 2000000 512 1024 ]
+ sender macarena/5022 [ t 2000000 100000 2000000 512 1024 ]
+ sender beguine/6000 [ t 2000000 100000 2000000 512 1024 ]
+
+ From Macarena:
+ wait until done with ACE
+ dest udp macarena/5000 <session name>
+ reserve wf [ cl 2000000 100000 2000000 512 1024 ]
+
+
+
+3. If RTAP runs fine and the daemons show the debug messages about
+ RESV, PATH and other RSVP messages, run the QoS example, making sure
+ that rtap session is released on both machines.
+
+-------------------------------------------------------------------------------
+
+If you run into any problems with this test please contact Vishal
+Kachroo <vishal@cs.wustl.edu>.
+
+This README last updated on 20th July, 2000.
+
+-------------------------------------------------------------------------------
diff --git a/ACE/examples/QOS/Change_Sender_TSpec/Receiver_QoS_Event_Handler.cpp b/ACE/examples/QOS/Change_Sender_TSpec/Receiver_QoS_Event_Handler.cpp
new file mode 100644
index 00000000000..d6ece4d563c
--- /dev/null
+++ b/ACE/examples/QOS/Change_Sender_TSpec/Receiver_QoS_Event_Handler.cpp
@@ -0,0 +1,145 @@
+/* -*- C++ -*- */
+// $Id$
+
+// ============================================================================
+//
+// = LIBRARY
+// ACE_wrappers/examples/QOS
+//
+// = FILENAME
+// Receiver_QoS_Event_Handler.cpp
+//
+// = AUTHOR
+// Vishal Kachroo <vishal@cs.wustl.edu>
+//
+// ============================================================================
+
+#include "Receiver_QoS_Event_Handler.h"
+#include "ace/Log_Msg.h"
+#include "ace/SString.h"
+#include "Fill_ACE_QoS.h"
+
+// Constructor.
+Receiver_QoS_Event_Handler::Receiver_QoS_Event_Handler (void)
+{
+}
+
+Receiver_QoS_Event_Handler::Receiver_QoS_Event_Handler (const ACE_SOCK_Dgram_Mcast_QoS
+ &dgram_mcast_qos,
+ ACE_QoS_Session *qos_session)
+ : dgram_mcast_qos_ (dgram_mcast_qos),
+ qos_session_ (qos_session)
+{
+}
+
+// Destructor.
+Receiver_QoS_Event_Handler::~Receiver_QoS_Event_Handler (void)
+{
+}
+
+// Return the handle of the Dgram_Mcast. This method is called
+// internally by the reactor.
+ACE_HANDLE
+Receiver_QoS_Event_Handler::get_handle (void) const
+{
+ return this->dgram_mcast_qos_.get_handle ();
+}
+
+// Called when there is a READ activity on the dgram_mcast_qos handle.
+int
+Receiver_QoS_Event_Handler::handle_input (ACE_HANDLE)
+{
+ char buf[BUFSIZ];
+
+ iovec iov;
+ iov.iov_base = buf;
+ iov.iov_len = BUFSIZ;
+
+ ACE_OS::memset (iov.iov_base,
+ 0,
+ BUFSIZ);
+
+ ACE_DEBUG ((LM_DEBUG,
+ "Inside handle_input () of Receiver_QoS_Event_Handler ()\n"));
+
+ // Receive message from multicast group.
+ ssize_t result =
+ this->dgram_mcast_qos_.recv (&iov,
+ 1,
+ this->remote_addr_);
+
+ if (result != -1)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ "Message Received : %s",
+ iov.iov_base));
+ return 0;
+ }
+ else
+ return -1;
+}
+
+// Called when there is a QoS Event.
+int
+Receiver_QoS_Event_Handler::handle_qos (ACE_HANDLE fd)
+{
+ ACE_UNUSED_ARG (fd);
+
+ ACE_DEBUG ((LM_DEBUG,
+ "\nReceived a QOS event. Inside handle_qos ()\n"));
+
+ // We have received an RSVP event. The following update_qos () call
+ // calls rapi_dispatch () in case of RAPI and WSAIoctl (GET_QOS) in
+ // case of W2K. It then does the QoS parameter translation and updates
+ // the QoS session object with the latest QoS. This call replaces the
+ // direct call that was being made to WSAIoctl (GET_QOS) here for the
+ // Win2K example.
+
+ if (this->qos_session_->update_qos () == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Error in updating QoS\n"),
+ -1);
+ else
+ ACE_DEBUG ((LM_DEBUG,
+ " Updating QOS succeeds.\n"));
+
+ // Now proactively query the QoS object for QoS.
+ ACE_QoS ace_get_qos = this->qos_session_->qos ();
+
+ ACE_DEBUG ((LM_DEBUG,
+ "\nReceiving Flowspec :\t\t\tSending Flowspec :\n\n"
+ "\tToken Rate = %d\t\t\tToken Rate = %d\n"
+ "\tToken Bucket Size = %d\t\t\tToken Bucket Size = %d\n"
+ "\tPeak Bandwidth = %d\t\t\tPeak Bandwidth = %d\n"
+ "\tLatency = %d\t\t\t\tLatency = %d\n"
+ "\tDelay Variation = %d\t\t\tDelay Variation = %d\n"
+ "\tService Type = %d\t\t\tService Type = %d\n"
+ "\tMax SDU Size = %d\t\t\tMax SDU Size = %d\n"
+ "\tMinimum Policed Size = %d\t\tMinimum Policed Size = %d\n\n",
+ ace_get_qos.receiving_flowspec ()->token_rate (),
+ ace_get_qos.sending_flowspec ()->token_rate (),
+ ace_get_qos.receiving_flowspec ()->token_bucket_size (),
+ ace_get_qos.sending_flowspec ()->token_bucket_size (),
+ ace_get_qos.receiving_flowspec ()->peak_bandwidth (),
+ ace_get_qos.sending_flowspec ()->peak_bandwidth (),
+ ace_get_qos.receiving_flowspec ()->latency (),
+ ace_get_qos.sending_flowspec ()->latency (),
+ ace_get_qos.receiving_flowspec ()->delay_variation (),
+ ace_get_qos.sending_flowspec ()->delay_variation (),
+ ace_get_qos.receiving_flowspec ()->service_type (),
+ ace_get_qos.sending_flowspec ()->service_type (),
+ ace_get_qos.receiving_flowspec ()->max_sdu_size (),
+ ace_get_qos.sending_flowspec ()->max_sdu_size (),
+ ace_get_qos.receiving_flowspec ()->minimum_policed_size (),
+ ace_get_qos.sending_flowspec ()->minimum_policed_size ()));
+
+
+return 0;
+
+}
+
+
+
+
+
+
diff --git a/ACE/examples/QOS/Change_Sender_TSpec/Receiver_QoS_Event_Handler.h b/ACE/examples/QOS/Change_Sender_TSpec/Receiver_QoS_Event_Handler.h
new file mode 100644
index 00000000000..874d628e3c1
--- /dev/null
+++ b/ACE/examples/QOS/Change_Sender_TSpec/Receiver_QoS_Event_Handler.h
@@ -0,0 +1,61 @@
+/* -*- C++ -*- */
+// $Id$
+
+// ============================================================================
+//
+// = LIBRARY
+// ACE_wrappers/examples/QOS
+//
+// = FILENAME
+// Receiver_QoS_Event_Handler.h
+//
+// = AUTHOR
+// Vishal Kachroo <vishal@cs.wustl.edu>
+//
+// ============================================================================
+
+#ifndef RECEIVER_QOS_EVENT_HANDLER_H
+#define RECEIVER_QOS_EVENT_HANDLER_H
+
+#include "ace/Reactor.h"
+#include "ace/INET_Addr.h"
+#include "ace/Event_Handler.h"
+#include "ace/QoS/QoS_Session.h"
+#include "ace/QoS/SOCK_Dgram_Mcast_QoS.h"
+
+ACE_RCSID(Receiver_QoS_Event_Handler, Receiver_QoS_Event_Handler, "$Id$")
+
+ class Receiver_QoS_Event_Handler : public ACE_Event_Handler
+ {
+ public:
+ // = Initialization and Termination methods.
+ Receiver_QoS_Event_Handler (void);
+ // Constructor.
+
+ Receiver_QoS_Event_Handler::Receiver_QoS_Event_Handler (const ACE_SOCK_Dgram_Mcast_QoS &dgram_mcast_qos,
+ ACE_QoS_Session *qos_session);
+ // Constructor.
+
+ ~Receiver_QoS_Event_Handler (void);
+ // Destructor.
+
+ virtual ACE_HANDLE get_handle (void) const;
+ // Override this to return the handle of the Dgram_Mcast
+ // that we are using.
+
+ virtual int handle_input (ACE_HANDLE fd);
+ // Handles a READ event.
+
+ virtual int handle_qos (ACE_HANDLE fd);
+ // Handles a QoS event.
+
+ private:
+ ACE_SOCK_Dgram_Mcast_QoS dgram_mcast_qos_;
+ ACE_QoS_Session *qos_session_;
+ ACE_INET_Addr remote_addr_;
+ };
+
+#endif /* RECEIVER_QOS_EVENT_HANDLER_H */
+
+
+
diff --git a/ACE/examples/QOS/Change_Sender_TSpec/Sender_QoS_Event_Handler.cpp b/ACE/examples/QOS/Change_Sender_TSpec/Sender_QoS_Event_Handler.cpp
new file mode 100644
index 00000000000..7688bc34373
--- /dev/null
+++ b/ACE/examples/QOS/Change_Sender_TSpec/Sender_QoS_Event_Handler.cpp
@@ -0,0 +1,221 @@
+/* -*- C++ -*- */
+// $Id$
+
+// ============================================================================
+//
+// = LIBRARY
+// ACE_wrappers/examples/QOS
+//
+// = FILENAME
+// Sender_QoS_Event_Handler.cpp
+//
+// = AUTHOR
+// Vishal Kachroo <vishal@cs.wustl.edu>
+//
+// ============================================================================
+
+#include "Sender_QoS_Event_Handler.h"
+#include "ace/Log_Msg.h"
+
+#include "Fill_ACE_QoS.h"
+
+// Constructor.
+Sender_QoS_Event_Handler::Sender_QoS_Event_Handler (void)
+{
+}
+
+// Constructor.
+Sender_QoS_Event_Handler::Sender_QoS_Event_Handler (const ACE_SOCK_Dgram_Mcast_QoS
+ &dgram_mcast_qos,
+ ACE_QoS_Session *qos_session)
+ : dgram_mcast_qos_ (dgram_mcast_qos),
+ qos_session_ (qos_session)
+{
+}
+
+// Destructor.
+Sender_QoS_Event_Handler::~Sender_QoS_Event_Handler (void)
+{
+}
+
+// Return the handle of the Dgram_Mcast. This method is called
+// internally by the reactor.
+
+ACE_HANDLE
+Sender_QoS_Event_Handler::get_handle (void) const
+{
+ return this->dgram_mcast_qos_.get_handle ();
+}
+
+// Handle the QoS Event. In this case send data to the receiver
+// using WSASendTo() that uses overlapped I/O.
+
+int
+Sender_QoS_Event_Handler::handle_qos (ACE_HANDLE)
+{
+ ACE_DEBUG ((LM_DEBUG,
+ "\nReceived a QOS event. Inside handle_qos ()\n"));
+
+ // We have received an RSVP event. The following update_qos () call
+ // calls rapi_dispatch () in case of RAPI and WSAIoctl (GET_QOS) in
+ // case of W2K. It then does the QoS parameter translation and updates
+ // the QoS session object with the latest QoS. This call replaces the
+ // direct call that was being made to WSAIoctl (GET_QOS) here for the
+ // Win2K example.
+
+ if (this->qos_session_->update_qos () == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Error in updating QoS\n"),
+ -1);
+ else
+ ACE_DEBUG ((LM_DEBUG,
+ " Updating QOS succeeds.\n"));
+
+ // Now proactively query the QoS object for QoS.
+ ACE_QoS ace_get_qos = this->qos_session_->qos ();
+
+ ACE_DEBUG ((LM_DEBUG,
+ "\nReceiving Flowspec :\t\t\tSending Flowspec :\n\n"
+ "\tToken Rate = %d\t\t\tToken Rate = %d\n"
+ "\tToken Bucket Size = %d\t\t\tToken Bucket Size = %d\n"
+ "\tPeak Bandwidth = %d\t\t\tPeak Bandwidth = %d\n"
+ "\tLatency = %d\t\t\t\tLatency = %d\n"
+ "\tDelay Variation = %d\t\t\tDelay Variation = %d\n"
+ "\tService Type = %d\t\t\tService Type = %d\n"
+ "\tMax SDU Size = %d\t\t\tMax SDU Size = %d\n"
+ "\tMinimum Policed Size = %d\t\tMinimum Policed Size = %d\n\n",
+ ace_get_qos.receiving_flowspec ()->token_rate (),
+ ace_get_qos.sending_flowspec ()->token_rate (),
+ ace_get_qos.receiving_flowspec ()->token_bucket_size (),
+ ace_get_qos.sending_flowspec ()->token_bucket_size (),
+ ace_get_qos.receiving_flowspec ()->peak_bandwidth (),
+ ace_get_qos.sending_flowspec ()->peak_bandwidth (),
+ ace_get_qos.receiving_flowspec ()->latency (),
+ ace_get_qos.sending_flowspec ()->latency (),
+ ace_get_qos.receiving_flowspec ()->delay_variation (),
+ ace_get_qos.sending_flowspec ()->delay_variation (),
+ ace_get_qos.receiving_flowspec ()->service_type (),
+ ace_get_qos.sending_flowspec ()->service_type (),
+ ace_get_qos.receiving_flowspec ()->max_sdu_size (),
+ ace_get_qos.sending_flowspec ()->max_sdu_size (),
+ ace_get_qos.receiving_flowspec ()->minimum_policed_size (),
+ ace_get_qos.sending_flowspec ()->minimum_policed_size ()));
+
+ // This is SPECIFIC TO WIN2K and should be done in the qos_update function.
+
+// ACE_QoS ace_get_qos;
+// u_long dwBytes;
+
+// if (ACE_OS::ioctl (this->dgram_mcast_qos_.get_handle (),
+// ACE_SIO_GET_QOS,
+// ace_get_qos,
+// &dwBytes) == -1)
+// ACE_ERROR ((LM_ERROR,
+// "Error in Qos get ACE_OS::ioctl ()\n"
+// "Bytes Returned = %d\n",
+// dwBytes));
+// else
+// ACE_DEBUG ((LM_DEBUG,
+// "Getting QOS using ACE_OS::ioctl () succeeds.\n"));
+
+ char* msg = "Hello sent on a QoS enabled session !!\n";
+ iovec iov[1];
+ iov[0].iov_base = msg;
+ iov[0].iov_len = ACE_OS::strlen(msg);
+
+ size_t bytes_sent = 0;
+
+ // Send "Hello" to the QoS session address to which the receiver has
+ // subscribed.
+ if (this->dgram_mcast_qos_.send (iov,
+ 1,
+ bytes_sent,
+ 0,
+ this->qos_session_->dest_addr (),
+ 0,
+ 0) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Error in dgram_mcast.send ()\n"),
+ -1);
+ else
+ ACE_DEBUG ((LM_DEBUG,
+ "Using ACE_OS::sendto () : Bytes sent : %d",
+ bytes_sent));
+
+ //
+ // create a dynamic flow spec on each callback to test QoS retransmits
+ //
+ ACE_CString flow_id ("flow_id");
+
+ Fill_ACE_QoS flow_spec_list;
+ ACE_DEBUG ((LM_DEBUG,
+ "\nA new flow spec! in QoS handler."));
+
+ static int token_rate = 9400;
+ ++token_rate;
+ static int peak_bw = 18500;
+ ++peak_bw;
+ switch (flow_spec_list.map ().bind (flow_id,
+ new ACE_Flow_Spec (token_rate,
+ 708,
+ peak_bw,
+ 0,
+ 0,
+ ACE_SERVICETYPE_CONTROLLEDLOAD,
+ 368,
+ 368,
+ 25,
+ 1)))
+ {
+ case 1 :
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Unable to bind the new flow spec\n"
+ "The Flow Spec name already exists\n"),
+ -1);
+ break;
+ case -1 :
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Unable to bind the new flow spec\n"),
+ -1);
+ break;
+ }
+
+ //
+ // set up the new qos
+ //
+ ACE_QoS another_qos_sender;
+ if (flow_spec_list.fill_simplex_sender_qos (another_qos_sender,
+ flow_id) !=0)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Unable to fill handler-simplex sender qos\n"),
+ -1);
+ else
+ ACE_DEBUG ((LM_DEBUG,
+ "Successfully built a new flowspec in handle_qos!\n"));
+
+ //
+ // change the qos for the current session
+ //
+ ACE_QoS_Manager qos_manager = this->dgram_mcast_qos_.qos_manager ();
+
+ ACE_DEBUG ((LM_DEBUG,
+ "QoS Manager was built in handle_qos!\n"));
+
+ // Set the QoS for the session. Replaces the ioctl () call that
+ // was being made previously.
+ if (this->qos_session_->qos (&this->dgram_mcast_qos_,
+ &qos_manager,
+ another_qos_sender) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Unable to set QoS\n"),
+ -1);
+ else
+ ACE_DEBUG ((LM_DEBUG,
+ "Setting QOS succeeds.\n"));
+
+
+ // ACE_SOCK_Dgram_Mcast_QoS dgram_mcast_qos_;
+ // ACE_QoS_Session *qos_session_;
+
+ return 0;
+}
diff --git a/ACE/examples/QOS/Change_Sender_TSpec/Sender_QoS_Event_Handler.h b/ACE/examples/QOS/Change_Sender_TSpec/Sender_QoS_Event_Handler.h
new file mode 100644
index 00000000000..b691bbd0615
--- /dev/null
+++ b/ACE/examples/QOS/Change_Sender_TSpec/Sender_QoS_Event_Handler.h
@@ -0,0 +1,61 @@
+/* -*- C++ -*- */
+// $Id$
+
+// ============================================================================
+//
+// = LIBRARY
+// ACE_wrappers/examples/QOS
+//
+// = FILENAME
+// Sender_QoS_Event_Handler.h
+//
+// = AUTHOR
+// Vishal Kachroo <vishal@cs.wustl.edu>
+//
+// ============================================================================
+
+#ifndef SENDER_QOS_EVENT_HANDLER_H
+#define SENDER_QOS_EVENT_HANDLER_H
+
+#include "ace/Event_Handler.h"
+#include "ace/Reactor.h"
+#include "ace/INET_Addr.h"
+#include "ace/QoS/SOCK_Dgram_Mcast_QoS.h"
+#include "ace/QoS/QoS_Session.h"
+
+//#define MY_DEFPORT 5001
+//#define DEFAULT_MULTICASTGROUP "234.5.6.7"
+
+ACE_RCSID(Sender_QoS_Event_Handler, Sender_QoS_Event_Handler, "$Id$")
+
+class Sender_QoS_Event_Handler : public ACE_Event_Handler
+{
+public:
+ // = Initialization and Termination methods.
+ Sender_QoS_Event_Handler (void);
+ // Constructor.
+
+ Sender_QoS_Event_Handler::Sender_QoS_Event_Handler (const ACE_SOCK_Dgram_Mcast_QoS
+ &dgram_mcast_qos,
+ ACE_QoS_Session *qos_session
+ );
+ // Constructor.
+
+ ~Sender_QoS_Event_Handler (void);
+ // Destructor.
+
+ virtual ACE_HANDLE get_handle (void) const;
+ // Override this to return the handle of the Dgram_Mcast
+ // that we are using.
+
+ virtual int handle_qos (ACE_HANDLE fd);
+ // Handles a QoS event. Right now, just
+ // prints a message.
+
+private:
+
+ ACE_SOCK_Dgram_Mcast_QoS dgram_mcast_qos_;
+ ACE_QoS_Session *qos_session_;
+};
+
+#endif /* SENDER_QOS_EVENT_HANDLER_H */
diff --git a/ACE/examples/QOS/Change_Sender_TSpec/receiver.cpp b/ACE/examples/QOS/Change_Sender_TSpec/receiver.cpp
new file mode 100644
index 00000000000..e5702b90c1c
--- /dev/null
+++ b/ACE/examples/QOS/Change_Sender_TSpec/receiver.cpp
@@ -0,0 +1,319 @@
+/* -*- C++ -*- */
+// $Id$
+
+// ============================================================================
+//
+// = LIBRARY
+// ACE_wrappers/examples/QOS
+//
+// = FILENAME
+// server.cpp
+//
+// = AUTHOR
+// Vishal Kachroo <vishal@cs.wustl.edu>
+//
+// ============================================================================
+
+#define QOSEVENT_MAIN
+
+#include "ace/QoS/QoS_Session.h"
+#include "ace/QoS/QoS_Session_Factory.h"
+#include "ace/QoS/QoS_Decorator.h"
+#include "ace/QoS/SOCK_Dgram_Mcast_QoS.h"
+
+#include "QoS_Util.h"
+#include "Fill_ACE_QoS.h"
+#include "QoS_Signal_Handler.h"
+#include "Receiver_QoS_Event_Handler.h"
+
+// To open QOS sockets administrative access is required on the
+// machine. Fill in default values for QoS structure. The default
+// values were simply choosen from existing QOS templates available
+// via WSAGetQosByName. Notice that ProviderSpecific settings are
+// being allowed when picking the "default" template but not for
+// "well-known" QOS templates. Also notice that since data is only
+// flowing from sender to receiver, different flowspecs are filled in
+// depending upon whether this application is acting as a sender or
+// receiver.
+
+
+// This function fills up the ACE_QoS_Params with the supplied iovec
+// and ACE_QoS.
+
+int
+FillQoSParams (ACE_QoS_Params &qos_params,
+ iovec* iov,
+ ACE_QoS* qos)
+{
+ qos_params.callee_data (iov);
+ qos_params.caller_data (0);
+ qos_params.socket_qos (qos);
+ qos_params.group_socket_qos (0);
+ qos_params.flags (ACE_JL_BOTH);
+
+ return 0;
+}
+
+int
+ACE_TMAIN (int argc, ACE_TCHAR * argv[])
+{
+
+ QoS_Util qos_util(argc, argv);
+
+ if (qos_util.parse_args () == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Error in parsing args\n"),
+ -1);
+
+ // This is a multicast application.
+ if (qos_util.multicast_flag ())
+ {
+ Fill_ACE_QoS fill_ace_qos;
+
+ // The application adds the flow specs that it wants into the
+ // Fill_ACE_QoS. The Fill_ACE_QoS indexes the flow specs by the
+ // flow spec names. Here the new flowspec being added is g_711.
+ ACE_CString g_711 ("g_711");
+
+ switch (fill_ace_qos.map ().bind (g_711,
+ new ACE_Flow_Spec (9200,
+ 708,
+ 18400,
+ 0,
+ 0,
+ ACE_SERVICETYPE_CONTROLLEDLOAD,
+ 368,
+ 368,
+ 25,
+ 1)))
+ {
+ case 1 :
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Unable to bind the new flow spec\n"
+ "The Flow Spec name already exists\n"),
+ -1);
+ break;
+ case -1 :
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Unable to bind the new flow spec\n"),
+ -1);
+ break;
+ }
+
+ ACE_DEBUG ((LM_DEBUG,
+ "g_711 Flow Spec bound successfully\n"));
+
+ // This is a receiver. So we fill in the receiving QoS parameters.
+ ACE_QoS ace_qos_receiver;
+ if (fill_ace_qos.fill_simplex_receiver_qos (ace_qos_receiver,
+ g_711) !=0)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Unable to fill simplex receiver qos\n"),
+ -1);
+ else
+ ACE_DEBUG ((LM_DEBUG,
+ "Filled up the Receiver QoS parameters\n"));
+
+ // Opening a new Multicast Datagram.
+ ACE_SOCK_Dgram_Mcast_QoS dgram_mcast_qos;
+
+ // Multicast Session Address specified by user at command line.
+ // If this address is not specified,
+ // <localhost:ACE_DEFAULT_MULTICAST_PORT> is assumed.
+ ACE_INET_Addr mult_addr (*(qos_util.mult_session_addr ()));
+
+ // Fill the ACE_QoS_Params to be passed to the <ACE_OS::join_leaf>
+ // through subscribe.
+
+ ACE_QoS_Params qos_params;
+ FillQoSParams (qos_params, 0, &ace_qos_receiver);
+
+ // Create a QoS Session Factory.
+ ACE_QoS_Session_Factory session_factory;
+
+ // Ask the factory to create a QoS session.
+ ACE_QoS_Session *qos_session =
+ session_factory.create_session ();
+
+ // Create a destination address for the QoS session. The same
+ // address should be used for the subscribe call later. A copy
+ // is made below only to distinguish the two usages of the dest
+ // address.
+
+ ACE_INET_Addr dest_addr (mult_addr);
+
+ // A QoS session is defined by the 3-tuple [DestAddr, DestPort,
+ // Protocol]. Initialize the QoS session.
+ if (qos_session->open (mult_addr,
+ IPPROTO_UDP) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Error in opening the QoS session\n"),
+ -1);
+ else
+ ACE_DEBUG ((LM_DEBUG,
+ "QoS session opened successfully\n"));
+
+ // The following call opens the Dgram_Mcast and calls the
+ // <ACE_OS::join_leaf> with the qos_params supplied here. Note
+ // the QoS session object is passed into this call. This
+ // subscribes the underlying socket to the passed in QoS
+ // session. For joining multiple multicast sessions, the
+ // following subscribe call should be made with different
+ // multicast addresses and a new QoS session object should be
+ // passed in for each such call. The QoS session objects can be
+ // created only through the session factory. Care should be
+ // taken that the mult_addr for the subscribe() call matches the
+ // dest_addr of the QoS session object. If this is not done, the
+ // subscribe call will fail. A more abstract version of
+ // subscribe will be added that constrains the various features
+ // of GQoS like different flags etc.
+
+ if (dgram_mcast_qos.subscribe (mult_addr,
+ qos_params,
+ 1,
+ 0,
+ AF_INET,
+ // ACE_FROM_PROTOCOL_INFO,
+ 0,
+ 0, // ACE_Protocol_Info,
+ 0,
+ ACE_OVERLAPPED_SOCKET_FLAG
+ | ACE_FLAG_MULTIPOINT_C_LEAF
+ | ACE_FLAG_MULTIPOINT_D_LEAF,
+ qos_session) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Error in subscribe\n"),
+ -1);
+ else
+ ACE_DEBUG ((LM_DEBUG,
+ "Dgram_Mcast subscribe succeeds \n"));
+
+ int nIP_TTL = 25;
+ char achInBuf [BUFSIZ];
+ u_long dwBytes;
+
+ // Should this be abstracted into QoS objects ?? Doesnt seem to have
+ // to do anything directly with QoS.
+ if (ACE_OS::ioctl (dgram_mcast_qos.get_handle (), // Socket.
+ ACE_SIO_MULTICAST_SCOPE, // IO control code.
+ &nIP_TTL, // In buffer.
+ sizeof (nIP_TTL), // Length of in buffer.
+ achInBuf, // Out buffer.
+ BUFSIZ, // Length of Out buffer.
+ &dwBytes, // bytes returned.
+ 0, // Overlapped.
+ 0) == -1) // Func.
+ ACE_ERROR ((LM_ERROR,
+ "Error in Multicast scope ACE_OS::ioctl() \n"));
+ else
+ ACE_DEBUG ((LM_DEBUG,
+ "Setting TTL with Multicast scope ACE_OS::ioctl call succeeds \n"));
+
+ int bFlag = 0;
+
+ // Should this be abstracted into QoS objects ?? Doesnt seem to have
+ // to do anything directly with QoS.
+ if (ACE_OS::ioctl (dgram_mcast_qos.get_handle (), // Socket.
+ ACE_SIO_MULTIPOINT_LOOPBACK, // IO control code.
+ &bFlag, // In buffer.
+ sizeof (bFlag), // Length of in buffer.
+ achInBuf, // Out buffer.
+ BUFSIZ, // Length of Out buffer.
+ &dwBytes, // bytes returned.
+ 0, // Overlapped.
+ 0) == -1) // Func.
+ ACE_ERROR ((LM_ERROR,
+ "Error in Loopback ACE_OS::ioctl() \n"));
+ else
+ ACE_DEBUG ((LM_DEBUG,
+ "Disable Loopback with ACE_OS::ioctl call succeeds \n"));
+
+ // This is a receiver.
+ qos_session->flags (ACE_QoS_Session::ACE_QOS_RECEIVER);
+
+ ACE_QoS_Manager qos_manager = dgram_mcast_qos.qos_manager ();
+
+ // Set the QoS for the session. Replaces the ioctl () call that
+ // was being made previously.
+ if (qos_session->qos (&dgram_mcast_qos,
+ &qos_manager,
+ ace_qos_receiver) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Unable to set QoS\n"),
+ -1);
+ else
+ ACE_DEBUG ((LM_DEBUG,
+ "Setting QOS succeeds.\n"));
+
+ // Register a signal handler that helps to gracefully close the
+ // open QoS sessions.
+ QoS_Signal_Handler qos_signal_handler (qos_session);
+
+ // Register the usual SIGINT signal handler with the Reactor for
+ // the application to gracefully release the QoS session and
+ // shutdown.
+ if (ACE_Reactor::instance ()->register_handler
+ (SIGINT, &qos_signal_handler) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Error in registering the Signal Handler.\n"),
+ -1);
+
+ // Handler to process QoS and Data events for the reciever.
+ Receiver_QoS_Event_Handler qos_event_handler (dgram_mcast_qos,
+ qos_session);
+
+ // Decorate the above handler with QoS functionality.
+ ACE_QoS_Decorator qos_decorator (&qos_event_handler,
+ qos_session);
+
+ // Initialize the Decorator.
+ if (qos_decorator.init () != 0)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "QoS Decorator init () failed.\n"),
+ -1);
+
+ // Register the decorated Event Handler with the Reactor.
+ if (ACE_Reactor::instance ()->register_handler (&qos_decorator,
+ ACE_Event_Handler::QOS_MASK |
+ ACE_Event_Handler::READ_MASK) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Error in registering the Decorator with the Reactor\n"),
+ -1);
+
+// // Register the RAPI Event Handler with the Reactor. This
+// // handles the QoS events.
+// if (ACE_Reactor::instance ()->register_handler
+// (&rapi_event_handler,
+// ACE_Event_Handler::QOS_MASK | ACE_Event_Handler::READ_MASK) == -1)
+// ACE_ERROR_RETURN ((LM_ERROR,
+// "Error in registering the RAPI Event Handler\n"),
+// -1);
+
+// // The following event handler handles the data.
+// ACE_QoS_Event_Handler data_event_handler (dgram_mcast_qos,
+// qos_session);
+
+// // Register the Data Event Handler with the Reactor.
+// if (ACE_Reactor::instance ()->register_handler
+// (&data_event_handler,ACE_Event_Handler::READ_MASK) == -1)
+// ACE_ERROR_RETURN ((LM_ERROR,
+// "Error in registering Data Event Handler\n"),
+// -1);
+
+ // Start the event loop.
+ ACE_DEBUG ((LM_DEBUG,
+ "Running the Event Loop ... \n"));
+
+ ACE_Reactor::instance ()->run_event_loop ();
+
+ ACE_DEBUG ((LM_DEBUG,
+ "(%P|%t) shutting down server logging daemon\n"));
+ }
+ else
+ ACE_DEBUG ((LM_DEBUG,
+ "Specify a -m option for multicast application\n"));
+ return 0;
+}
+
+
+
diff --git a/ACE/examples/QOS/Change_Sender_TSpec/sender.cpp b/ACE/examples/QOS/Change_Sender_TSpec/sender.cpp
new file mode 100644
index 00000000000..68d8d1a5586
--- /dev/null
+++ b/ACE/examples/QOS/Change_Sender_TSpec/sender.cpp
@@ -0,0 +1,313 @@
+/* -*- C++ -*- */
+// $Id$
+
+// ============================================================================
+//
+// = LIBRARY
+// ACE_wrappers/examples/QOS
+//
+// = FILENAME
+// client.cpp
+//
+// = AUTHOR
+// Vishal Kachroo <vishal@cs.wustl.edu>
+//
+// ============================================================================
+
+
+#include "ace/QoS/QoS_Session.h"
+#include "ace/QoS/QoS_Session_Factory.h"
+#include "ace/QoS/QoS_Session_Impl.h"
+#include "ace/QoS/QoS_Decorator.h"
+#include "ace/QoS/SOCK_Dgram_Mcast_QoS.h"
+
+#include "QoS_Util.h"
+#include "Fill_ACE_QoS.h"
+#include "QoS_Signal_Handler.h"
+#include "Sender_QoS_Event_Handler.h"
+
+// To open QOS sockets administrative access is required on the
+// machine. Fill in default values for QoS structure. The default
+// values were simply choosen from existing QOS templates available
+// via WSAGetQosByName. Notice that ProviderSpecific settings are
+// being allowed when picking the "default" template but not for
+// "well-known" QOS templates. Also notice that since data is only
+// flowing from sender to receiver, different flowspecs are filled in
+// depending upon whether this application is acting as a sender or
+// receiver.
+
+// This function fills up the ACE_QoS_Params with the supplied iovec and ACE_QoS.
+
+int
+FillQoSParams (ACE_QoS_Params &qos_params,
+ iovec* iov,
+ ACE_QoS* qos)
+{
+ qos_params.callee_data (iov);
+ qos_params.caller_data (0);
+ qos_params.socket_qos (qos);
+ qos_params.group_socket_qos (0);
+ qos_params.flags (ACE_JL_BOTH);
+
+ return 0;
+}
+
+int
+ACE_TMAIN (int argc, ACE_TCHAR * argv[])
+{
+
+ ACE_DEBUG ((LM_DEBUG,
+ "Sender\n"));
+
+ QoS_Util qos_util(argc, argv);
+
+ if (qos_util.parse_args () == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Error in parsing args\n"),
+ -1);
+
+ // This is a multicast application.
+ if (qos_util.multicast_flag ())
+ {
+ Fill_ACE_QoS fill_ace_qos;
+
+ // The application adds the flow specs that it wants into the
+ // Fill_ACE_QoS. The Fill_ACE_QoS indexes the flow specs by the flow
+ // spec names. Here the new flowspec being added is g_711.
+ ACE_CString g_711 ("g_711");
+
+ switch (fill_ace_qos.map ().bind (g_711,
+ new ACE_Flow_Spec (9200,
+ 708,
+ 18400,
+ 0,
+ 0,
+ ACE_SERVICETYPE_CONTROLLEDLOAD,
+ 368,
+ 368,
+ 25,
+ 1)))
+ {
+ case 1 :
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Unable to bind the new flow spec\n"
+ "The Flow Spec name already exists\n"),
+ -1);
+ break;
+ case -1 :
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Unable to bind the new flow spec\n"),
+ -1);
+ break;
+ }
+
+ ACE_DEBUG ((LM_DEBUG,
+ "g_711 Flow Spec bound successfully\n"));
+
+ // This is a sender. So we fill in the sending QoS parameters.
+ ACE_QoS ace_qos_sender;
+
+ if (fill_ace_qos.fill_simplex_sender_qos (ace_qos_sender,
+ g_711) !=0)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Unable to fill simplex sender qos\n"),
+ -1);
+ else
+ ACE_DEBUG ((LM_DEBUG,
+ "Filled up the Sender QoS parameters\n"));
+
+ // Opening a new Multicast Datagram. It is absolutely necessary that
+ // the sender and the receiver subscribe to the same multicast
+ // addresses to make sure the "multicast sessions" for the two are
+ // the same. This is used to match the RESV<->PATH states.
+ ACE_SOCK_Dgram_Mcast_QoS dgram_mcast_qos;
+
+ // Multicast Session Address specified by user at command line.
+ // If this address is not specified,
+ // <localhost:ACE_DEFAULT_MULTICAST_PORT> is assumed.
+ ACE_INET_Addr mult_addr (*(qos_util.mult_session_addr ()));
+
+ // Fill the ACE_QoS_Params to be passed to the <ACE_OS::join_leaf>
+ // through subscribe.
+
+ ACE_QoS_Params qos_params;
+ FillQoSParams (qos_params, 0, &ace_qos_sender);
+
+ // Create a QoS Session Factory.
+ ACE_QoS_Session_Factory session_factory;
+
+ // Ask the factory to create a QoS session.
+ ACE_QoS_Session *qos_session =
+ session_factory.create_session ();
+
+ // Create a destination address for the QoS session. The same
+ // address should be used for the subscribe call later. A copy is
+ // made below only to distinguish the two usages of the dest
+ // address.
+
+ ACE_INET_Addr dest_addr (mult_addr);
+
+ // A QoS session is defined by the 3-tuple [DestAddr, DestPort,
+ // Protocol]. Initialize the QoS session.
+ if (qos_session->open (mult_addr,
+ IPPROTO_UDP) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Error in opening the QoS session\n"),
+ -1);
+ else
+ ACE_DEBUG ((LM_DEBUG,
+ "QoS session opened successfully\n"));
+
+ // The following call opens the Dgram_Mcast and calls the
+ // <ACE_OS::join_leaf> with the qos_params supplied here. Note the
+ // QoS session object is passed into this call. This subscribes the
+ // underlying socket to the passed in QoS session. For joining
+ // multiple multicast sessions, the following subscribe call should
+ // be made with different multicast addresses and a new QoS session
+ // object should be passed in for each such call. The QoS session
+ // objects can be created only through the session factory. Care
+ // should be taken that the mult_addr for the subscribe() call
+ // matches the dest_addr of the QoS session object. If this is not
+ // done, the subscribe call will fail. A more abstract version of
+ // subscribe will be added that constrains the various features of
+ // GQoS like different flags etc.
+
+ if (dgram_mcast_qos.subscribe (mult_addr,
+ qos_params,
+ 1,
+ 0,
+ AF_INET,
+ // ACE_FROM_PROTOCOL_INFO,
+ 0,
+ 0, // ACE_Protocol_Info,
+ 0,
+ ACE_OVERLAPPED_SOCKET_FLAG
+ | ACE_FLAG_MULTIPOINT_C_LEAF
+ | ACE_FLAG_MULTIPOINT_D_LEAF,
+ qos_session) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Error in subscribe\n"),
+ -1);
+ else
+ ACE_DEBUG ((LM_DEBUG,
+ "Dgram_Mcast subscribe succeeds \n"));
+
+ int nIP_TTL = 25;
+ char achInBuf [BUFSIZ];
+ u_long dwBytes;
+
+ // Should this be abstracted into QoS objects ?? Doesnt seem to have
+ // to do anything directly with QoS.
+ if (ACE_OS::ioctl (dgram_mcast_qos.get_handle (), // Socket.
+ ACE_SIO_MULTICAST_SCOPE, // IO control code.
+ &nIP_TTL, // In buffer.
+ sizeof (nIP_TTL), // Length of in buffer.
+ achInBuf, // Out buffer.
+ BUFSIZ, // Length of Out buffer.
+ &dwBytes, // bytes returned.
+ 0, // Overlapped.
+ 0) == -1) // Func.
+ ACE_ERROR ((LM_ERROR,
+ "Error in Multicast scope ACE_OS::ioctl() \n"));
+ else
+ ACE_DEBUG ((LM_DEBUG,
+ "Setting TTL with Multicast scope ACE_OS::ioctl call succeeds \n"));
+
+ int bFlag = 0;
+
+ // Should this be abstracted into QoS objects ?? Doesnt seem to have
+ // to do anything directly with QoS.
+ if (ACE_OS::ioctl (dgram_mcast_qos.get_handle (), // Socket.
+ ACE_SIO_MULTIPOINT_LOOPBACK, // IO control code.
+ &bFlag, // In buffer.
+ sizeof (bFlag), // Length of in buffer.
+ achInBuf, // Out buffer.
+ BUFSIZ, // Length of Out buffer.
+ &dwBytes, // bytes returned.
+ 0, // Overlapped.
+ 0) == -1) // Func.
+ ACE_ERROR ((LM_ERROR,
+ "Error in Loopback ACE_OS::ioctl() \n"));
+ else
+ ACE_DEBUG ((LM_DEBUG,
+ "Disable Loopback with ACE_OS::ioctl call succeeds \n"));
+
+ // This is a sender.
+ qos_session->flags (ACE_QoS_Session::ACE_QOS_SENDER);
+
+ ACE_QoS_Manager qos_manager = dgram_mcast_qos.qos_manager ();
+
+ // Since we are using RSVP, it is imperative that the client
+ // application have the option of supplying the source sender
+ // port for the RSVP messages. A default will be chosen by the
+ // ACE API if this is not done.
+ qos_session->source_port (qos_util.source_port ());
+
+ // Set the QoS for the session. Replaces the ioctl () call that
+ // was being made previously.
+ if (qos_session->qos (&dgram_mcast_qos,
+ &qos_manager,
+ ace_qos_sender) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Unable to set QoS\n"),
+ -1);
+ else
+ ACE_DEBUG ((LM_DEBUG,
+ "Setting QOS succeeds.\n"));
+
+ // Register a signal handler that helps to gracefully close the open
+ // QoS sessions.
+ QoS_Signal_Handler qos_signal_handler (qos_session);
+
+ // Register the usual SIGINT signal handler with the Reactor for
+ // the application to gracefully release the QoS session and
+ // shutdown.
+ if (ACE_Reactor::instance ()->register_handler
+ (SIGINT, &qos_signal_handler) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Error in registering the Signal Handler.\n"),
+ -1);
+
+ // Handler to process QoS and Data events for the reciever.
+ Sender_QoS_Event_Handler qos_event_handler (dgram_mcast_qos,
+ qos_session);
+
+ // Decorate the above handler with QoS functionality.
+ ACE_QoS_Decorator qos_decorator (&qos_event_handler,
+ qos_session);
+
+ // Initialize the Decorator.
+ if (qos_decorator.init () != 0)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "QoS Decorator init () failed.\n"),
+ -1);
+
+ // Register the decorated Event Handler with the Reactor.
+ if (ACE_Reactor::instance ()->register_handler (&qos_decorator,
+ ACE_Event_Handler::QOS_MASK |
+ ACE_Event_Handler::READ_MASK) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Error in registering the Decorator with the Reactor\n"),
+ -1);
+
+ // Start the event loop.
+ ACE_DEBUG ((LM_DEBUG,
+ "Running the Event Loop ... \n"));
+
+ ACE_Reactor::instance ()->run_event_loop ();
+
+ ACE_DEBUG ((LM_DEBUG,
+ "(%P|%t) shutting down server logging daemon\n"));
+ }
+ else
+ ACE_DEBUG ((LM_DEBUG,
+ "Specify a -m option for multicast application\n"));
+ return 0;
+}
+
+
+
+
+
+
+
diff --git a/ACE/examples/QOS/Diffserv/Makefile.am b/ACE/examples/QOS/Diffserv/Makefile.am
new file mode 100644
index 00000000000..e94221278a2
--- /dev/null
+++ b/ACE/examples/QOS/Diffserv/Makefile.am
@@ -0,0 +1,62 @@
+## Process this file with automake to create Makefile.in
+##
+## $Id$
+##
+## This file was generated by MPC. Any changes made directly to
+## this file will be lost the next time it is generated.
+##
+## MPC Command:
+## /acebuilds/ACE_wrappers-repository/bin/mwc.pl -include /acebuilds/MPC/config -include /acebuilds/MPC/templates -feature_file /acebuilds/ACE_wrappers-repository/local.features -noreldefs -type automake -exclude build,Kokyu
+
+ACE_BUILDDIR = $(top_builddir)
+ACE_ROOT = $(top_srcdir)
+
+noinst_PROGRAMS =
+
+## Makefile.QOS_Diffserv_Client.am
+
+if BUILD_QOS
+if !BUILD_ACE_FOR_TAO
+noinst_PROGRAMS += client
+
+client_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR) \
+ -DACE_HAS_QOS
+
+client_SOURCES = \
+ diffserv_test.cpp
+
+client_LDADD = \
+ $(ACE_BUILDDIR)/ace/QoS/libACE_QoS.la \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+endif !BUILD_ACE_FOR_TAO
+endif BUILD_QOS
+
+## Makefile.QOS_Diffserv_Server.am
+
+if BUILD_QOS
+noinst_PROGRAMS += server
+
+server_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR) \
+ -DACE_HAS_QOS
+
+server_SOURCES = \
+ server.cpp
+
+server_LDADD = \
+ $(ACE_BUILDDIR)/ace/QoS/libACE_QoS.la \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+endif BUILD_QOS
+
+## Clean up template repositories, etc.
+clean-local:
+ -rm -f *~ *.bak *.rpo *.sym lib*.*_pure_* core core.*
+ -rm -f gcctemp.c gcctemp so_locations *.ics
+ -rm -rf cxx_repository ptrepository ti_files
+ -rm -rf templateregistry ir.out
+ -rm -rf ptrepository SunWS_cache Templates.DB
diff --git a/ACE/examples/QOS/Diffserv/NOTES.txt b/ACE/examples/QOS/Diffserv/NOTES.txt
new file mode 100644
index 00000000000..4e73c66af0f
--- /dev/null
+++ b/ACE/examples/QOS/Diffserv/NOTES.txt
@@ -0,0 +1,58 @@
+# $Id$
+
+Linux notes
+===========
+
+Under Linux kernel 2.4, the following DSCP values
+could not be set with the setsockopt call
+unless you run as root:
+
+EF, CS5, CS6, CS7
+
+Also, under Linux 2.4.2 kernel, if I could successfully
+set the 2 bits reserved for ECN in the Diffserv Field to
+0x00 or 0x02. However, the setsockopt call would
+fail if it was set to 0x01 or 0x03.
+
+According to the Linux Diffserv mailing list:
+http://diffserv.sourceforge.net
+http://www.geocrawler.com/archives/3/11111/2001/10/0/6761099/
+
+===========================================================================
+On Fri, Oct 05, 2001 at 08:18:06AM +0300, Pekka Savola wrote:
+> On Tue, 2 Oct 2001, Craig Rodrigues wrote:
+> > Can someone shed some light as to why I got this
+> > error under Linux? Is it configuration problem,
+> > or is there some sort of policy decision in the kernel that
+> > requires the process to be run as root when setting
+> > those DSCP values?
+>
+> A part of DSCP field was previously Precedence.
+>
+> Linux has required that in order to use 'Critical' or higher Precedence,
+> one must have CAP_NET_ADMIN capability, in most cases, root.
+>
+> I'm not one to say whether this restriction should be removed. Perhaps.
+>
+> --
+> Pekka Savola "Tell me of difficulties surmounted,
+> Netcore Oy not those you stumble over and fall"
+> Systems. Networks. Security. -- Robert Jordan: A Crown of Swords
+>
+===========================================================================
+
+FreeBSD notes
+=============
+Under FreeBSD 4.3, I encountered no problems
+setting DSCP or ECN values, and I could set all
+these values without being root.
+However, FreeBSD seems to be more fussy about the size of the parameter
+you pass into the setsockopt call. Make sure you get the
+size right, and cast it properly, ie. don't cast a short, or some
+other size.
+
+
+Solaris notes
+=============
+No problems setting DSCP or ECN values.
+
diff --git a/ACE/examples/QOS/Diffserv/QOS_Diffserv.mpc b/ACE/examples/QOS/Diffserv/QOS_Diffserv.mpc
new file mode 100644
index 00000000000..3e66fbee34a
--- /dev/null
+++ b/ACE/examples/QOS/Diffserv/QOS_Diffserv.mpc
@@ -0,0 +1,18 @@
+// -*- MPC -*-
+// $Id$
+
+project(*client) : aceexe, qos {
+ avoids += ace_for_tao
+ exename = client
+ requires += qos
+ Source_Files {
+ diffserv_test.cpp
+ }
+}
+project(*server) : aceexe, qos {
+ exename = server
+ requires += qos
+ Source_Files {
+ server.cpp
+ }
+}
diff --git a/ACE/examples/QOS/Diffserv/README b/ACE/examples/QOS/Diffserv/README
new file mode 100644
index 00000000000..285d514ad12
--- /dev/null
+++ b/ACE/examples/QOS/Diffserv/README
@@ -0,0 +1,107 @@
+This directory contains an example which
+tests the setting of the Diffserv Codepoint (DSCP)
+values in the
+IP TOS field of a stream of UDP packets.
+
+Running the example
+===================
+
+(1) On one host, run:
+ server [UDP port number]
+
+ If port number is omitted, a default port number of 20002
+ is used.
+
+(2) On a second host, run:
+ diffserv_test [destination host] [destination port]
+
+ The host and port of where the server is running should
+ be specified.
+
+ A stream of UDP packets will be sent from to the server,
+ with various codepoints set.
+
+(3) Look at the Diffserv Field (formerly known as the TOS field)
+ of your packets, using a protocol analyzer, such as Ethereal.
+
+
+
+
+Introduction
+============
+In RFC 2474, the Type of Service (TOS) field in
+the IP header was renamed the Diffserv (DS) field.
+The DS field is one octet (8 bits).
+
+ 0 1 2 3 4 5 6 7
+ +---+---+---+---+---+---+---+---+
+ | DSCP | ECN |
+ +---+---+---+---+---+---+---+---+
+
+The first 6 bits of the field are
+reserved for the Diffserv Codepoint (DSCP).
+There are 64 possible values (0-63) for the DSCP.
+
+Bits 6 and 7 of the DS field are reserved
+for Explicit Congestion Notification (ECN).
+ECN is defined in RFC 3168.
+
+
+Per-Hop Behaviors (PHB)
+=======================
+
+A Per-Hop Behavior (PHB) is a description of the externally
+observable forwarding treatment applied at a differentiated
+services compliant node.
+
+Certain PHB's are defined in RFC's and associated with
+different DSCP values. Other values are undefined and left
+for experimentation. Please refer to the RFC's for a full
+explanation of the attributes of the various PHB's.
+
+
+DSCP value PHB RFC
+(binary)
+-----------------------------------------------------------
+000000 Default (Best Effort) 2474
+001000 Class Selector (CS1) 2474
+010000 Class Selector (CS2) 2474
+011000 Class Selector (CS3) 2474
+100000 Class Selector (CS4) 2474
+101000 Class Selector (CS5) 2474
+110000 Class Selector (CS6) 2474
+111000 Class Selector (CS7) 2474
+001010 Assured Forwarding (AF11) 2597
+001100 Assured Forwarding (AF12) 2597
+001110 Assured Forwarding (AF13) 2597
+010010 Assured Forwarding (AF21) 2597
+010100 Assured Forwarding (AF22) 2597
+010110 Assured Forwarding (AF23) 2597
+011010 Assured Forwarding (AF31) 2597
+011100 Assured Forwarding (AF32) 2597
+011110 Assured Forwarding (AF33) 2597
+100010 Assured Forwarding (AF41) 2597
+100100 Assured Forwarding (AF42) 2597
+100110 Assured Forwarding (AF43) 2597
+101110 Expedited Forwarding (EF) 2598
+
+
+References
+==========
+RFC 2474, "Definition of the Differentiated Services (DS Field)
+ in the IPv4 and IPv6 Headers", http://www.ietf.org/rfc/rfc2474.txt
+
+RFC 2475, "An Architecture for Differentiated Services",
+ http://www.ietf.org/rfc/rfc2475.txt
+
+RFC 2597, "Assured Forwarding PHB Group", http://www.ietf.org/rfc/rfc2597.txt
+
+RFC 3246, "An Expedited Forwarding PHB", http://www.ietf.org/rfc/rfc3246.txt
+
+RFC 3247, "Supplemental Information for the New Definition of the EF PHB",
+ http://www.ietf.org/rfc/rfc3247.txt
+
+RFC 3168, "The Addition of Explicit Congestion Notification (ECN)
+ to IP", http://www.ietf.org/rfc/rfc3168.txt
+
+Ethereal, http://www.ethereal.com
diff --git a/ACE/examples/QOS/Diffserv/diffserv_test.cpp b/ACE/examples/QOS/Diffserv/diffserv_test.cpp
new file mode 100644
index 00000000000..1969616ea32
--- /dev/null
+++ b/ACE/examples/QOS/Diffserv/diffserv_test.cpp
@@ -0,0 +1,136 @@
+//=============================================================================
+/**
+ * @file diffserv_test.cpp
+ *
+ * $Id$
+ *
+ * @author Craig Rodrigues <crodrigu@bbn.com>
+ * @brief Send UDP packets to a destination host and port.
+ * Change the Diffserv field to various values.
+ */
+//=============================================================================
+
+#include "ace/Log_Msg.h"
+#include "ace/SOCK_CODgram.h"
+#include "ace/INET_Addr.h"
+#include "ace/OS_NS_string.h"
+#include "ace/OS_NS_stdlib.h"
+#include "ace/OS_NS_unistd.h"
+
+#define IPDSFIELD_DSCP_DEFAULT 0x00
+#define IPDSFIELD_DSCP_CS1 0x08
+#define IPDSFIELD_DSCP_CS2 0x10
+#define IPDSFIELD_DSCP_CS3 0x18
+#define IPDSFIELD_DSCP_CS4 0x20
+#define IPDSFIELD_DSCP_CS5 0x28
+#define IPDSFIELD_DSCP_CS6 0x30
+#define IPDSFIELD_DSCP_CS7 0x38
+#define IPDSFIELD_DSCP_AF11 0x0A
+#define IPDSFIELD_DSCP_AF12 0x0C
+#define IPDSFIELD_DSCP_AF13 0x0E
+#define IPDSFIELD_DSCP_AF21 0x12
+#define IPDSFIELD_DSCP_AF22 0x14
+#define IPDSFIELD_DSCP_AF23 0x16
+#define IPDSFIELD_DSCP_AF31 0x1A
+#define IPDSFIELD_DSCP_AF32 0x1C
+#define IPDSFIELD_DSCP_AF33 0x1E
+#define IPDSFIELD_DSCP_AF41 0x22
+#define IPDSFIELD_DSCP_AF42 0x24
+#define IPDSFIELD_DSCP_AF43 0x26
+#define IPDSFIELD_DSCP_EF 0x2E
+#define IPDSFIELD_ECT_MASK 0x02
+#define IPDSFIELD_CE_MASK 0x01
+
+int dscp [] =
+ {
+ IPDSFIELD_DSCP_DEFAULT ,
+ IPDSFIELD_DSCP_CS1 ,
+ IPDSFIELD_DSCP_CS2 ,
+ IPDSFIELD_DSCP_CS3 ,
+ IPDSFIELD_DSCP_CS4 ,
+ IPDSFIELD_DSCP_CS5 ,
+ IPDSFIELD_DSCP_CS6 ,
+ IPDSFIELD_DSCP_CS7 ,
+ IPDSFIELD_DSCP_AF11 ,
+ IPDSFIELD_DSCP_AF12 ,
+ IPDSFIELD_DSCP_AF13 ,
+ IPDSFIELD_DSCP_AF21 ,
+ IPDSFIELD_DSCP_AF22 ,
+ IPDSFIELD_DSCP_AF23 ,
+ IPDSFIELD_DSCP_AF31 ,
+ IPDSFIELD_DSCP_AF32 ,
+ IPDSFIELD_DSCP_AF33 ,
+ IPDSFIELD_DSCP_AF41 ,
+ IPDSFIELD_DSCP_AF42 ,
+ IPDSFIELD_DSCP_AF43 ,
+ IPDSFIELD_DSCP_EF
+ };
+
+const char *dscp_char[]=
+ {
+ "Normal",
+ "CS1",
+ "CS2",
+ "CS3",
+ "CS4",
+ "CS5",
+ "CS6",
+ "CS7",
+ "Assured Forwarding 11",
+ "Assured Forwarding 12",
+ "Assured Forwarding 13",
+ "Assured Forwarding 21",
+ "Assured Forwarding 22",
+ "Assured Forwarding 23",
+ "Assured Forwarding 31",
+ "Assured Forwarding 32",
+ "Assured Forwarding 33",
+ "Assured Forwarding 41",
+ "Assured Forwarding 42",
+ "Assured Forwarding 43",
+ "Expedited Forwarding"
+ };
+
+int
+ACE_TMAIN (int argc , ACE_TCHAR *argv[])
+{
+
+ if(argc != 3)
+ {
+ ACE_DEBUG((LM_DEBUG, "Usage:\n %s [destination host] [destination port]\n\n", argv[0]));
+ ACE_OS::exit(1);
+ }
+
+
+ char *buf = (char *)ACE_OS::malloc(20 * sizeof(char));
+ ACE_OS::strcpy(buf, "Hello");
+
+ ACE_SOCK_CODgram sock;
+ ACE_INET_Addr raddr(ACE_OS::atoi(argv[2]), argv[1]);
+
+ sock.open( raddr, ACE_Addr::sap_any, PF_INET, 0, 1);
+ int opt=0;
+ int ret =0, ret2=0;
+ unsigned int i;
+ for(i=0; i < 21; i++)
+ {
+ opt = dscp[i] << 2;
+ ret = sock.set_option(IPPROTO_IP, IP_TOS, (int *)&opt, (int)sizeof(opt) );
+ if(ret == -1){
+ ACE_DEBUG((LM_DEBUG, "setsockopt error: %m\n"));
+ }
+
+ for (int j=0; j<3; j++)
+ {
+ ret2 = sock.send(buf, ACE_OS::strlen(buf));
+ if(ret2 == -1){
+ ACE_DEBUG((LM_DEBUG, "send error: %m\n"));
+ }
+ printf("opt: %u dscp: %u, %s, setsockopt returned: %d, send returned: %d\n", opt, opt >> 2, dscp_char[i], ret, ret2);
+ ACE_OS::sleep(1);
+ }
+ }
+
+ ACE_OS::free(buf);
+ return 0;
+}
diff --git a/ACE/examples/QOS/Diffserv/run_test.pl b/ACE/examples/QOS/Diffserv/run_test.pl
new file mode 100755
index 00000000000..aef0765bac8
--- /dev/null
+++ b/ACE/examples/QOS/Diffserv/run_test.pl
@@ -0,0 +1,40 @@
+eval '(exit $?0)' && eval 'exec perl -S $0 ${1+"$@"}'
+ & eval 'exec perl -S $0 $argv:q'
+ if 0;
+
+# $Id$
+# -*- perl -*-
+
+use lib "$ENV{ACE_ROOT}/bin";
+use PerlACE::Run_Test;
+
+$iorfile = PerlACE::LocalFile ("ior");
+
+unlink $iorfile;
+$status = 0;
+
+$CL = new PerlACE::Process ("diffserv_test", "localhost 20002");
+$SV = new PerlACE::Process ("server");
+
+$server = $SV->Spawn ();
+$SV->TimedWait(2);
+
+$client = $CL->SpawnWaitKill (200);
+
+if ($client != 0) {
+ $time = localtime;
+ print STDERR "ERROR: client returned $client at $time\n";
+ $status = 1;
+}
+
+$server = $SV->WaitKill (400);
+
+if ($server != 0) {
+ $time = localtime;
+ print STDERR "ERROR: server returned $server at $time\n";
+ $status = 1;
+}
+
+unlink $iorfile;
+
+exit $status;
diff --git a/ACE/examples/QOS/Diffserv/server.cpp b/ACE/examples/QOS/Diffserv/server.cpp
new file mode 100644
index 00000000000..a1030d775e9
--- /dev/null
+++ b/ACE/examples/QOS/Diffserv/server.cpp
@@ -0,0 +1,163 @@
+//=============================================================================
+/**
+ * @file server.cpp
+ *
+ * $Id$
+ *
+ * @author Craig Rodrigues <crodrigu@bbn.com>
+ * @brief Start a server which listens for UDP packets on a specified port.
+ */
+//=============================================================================
+
+#include "ace/Reactor.h"
+#include "ace/Process.h"
+#include "ace/SOCK_Dgram.h"
+#include "ace/INET_Addr.h"
+#include "ace/Log_Msg.h"
+
+// Port used to receive for dgrams.
+static u_short port1;
+
+class Dgram_Endpoint : public ACE_Event_Handler
+{
+public:
+ Dgram_Endpoint (const ACE_INET_Addr &local_addr);
+
+ // = Hook methods inherited from the <ACE_Event_Handler>.
+ virtual ACE_HANDLE get_handle (void) const;
+ virtual int handle_input (ACE_HANDLE handle);
+ virtual int handle_timeout (const ACE_Time_Value & tv,
+ const void *arg = 0);
+ virtual int handle_close (ACE_HANDLE handle,
+ ACE_Reactor_Mask close_mask);
+
+ int send (const char *buf, size_t len, const ACE_INET_Addr &);
+ // Send the <buf> to the peer.
+
+private:
+ ACE_SOCK_Dgram endpoint_;
+ // Wrapper for sending/receiving dgrams.
+};
+
+int
+Dgram_Endpoint::send (const char *buf,
+ size_t len,
+ const ACE_INET_Addr &addr)
+{
+ return this->endpoint_.send (buf, len, addr);
+}
+
+Dgram_Endpoint::Dgram_Endpoint (const ACE_INET_Addr &local_addr)
+ : endpoint_ (local_addr)
+{
+}
+
+ACE_HANDLE
+Dgram_Endpoint::get_handle (void) const
+{
+ return this->endpoint_.get_handle ();
+}
+
+int
+Dgram_Endpoint::handle_close (ACE_HANDLE handle,
+ ACE_Reactor_Mask)
+{
+ ACE_UNUSED_ARG (handle);
+
+ this->endpoint_.close ();
+ delete this;
+ return 0;
+}
+
+int
+Dgram_Endpoint::handle_input (ACE_HANDLE)
+{
+ char buf[BUFSIZ];
+ ACE_INET_Addr from_addr;
+
+ ssize_t n = this->endpoint_.recv (buf,
+ sizeof buf,
+ from_addr);
+
+ if (n == -1)
+ ACE_ERROR ((LM_ERROR,
+ "%p\n",
+ "handle_input"));
+ else
+ {
+ buf[n] = 0;
+ ACE_DEBUG ((LM_DEBUG,
+ "Received buf of size %d = %s\n",
+ n,
+ buf));
+ }
+ return 0;
+}
+
+int
+Dgram_Endpoint::handle_timeout (const ACE_Time_Value &,
+ const void *)
+{
+ ACE_DEBUG ((LM_DEBUG,
+ "(%P|%t) timed out for endpoint\n"));
+ return 0;
+}
+
+static int
+run_test (u_short localport)
+{
+ ACE_INET_Addr local_addr (localport);
+
+ Dgram_Endpoint *endpoint;
+
+ ACE_NEW_RETURN (endpoint,
+ Dgram_Endpoint (local_addr),
+ -1);
+
+ ACE_DEBUG((LM_DEBUG, "Starting server on port %d\n",port1));
+
+ // Read data from other side.
+ if (ACE_Reactor::instance ()->register_handler
+ (endpoint,
+ ACE_Event_Handler::READ_MASK) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "ACE_Reactor::register_handler"),
+ -1);
+
+ int ret;
+ while(1){
+ ACE_Time_Value tv(10, 0);
+ ret = ACE_Reactor::instance ()->handle_events (&tv);
+ /* Error occurred while handling event */
+ if (ret < 0)
+ {
+ ACE_ERROR_RETURN ((LM_DEBUG,
+ "(%P|%t) %p\n",
+ "handle_events"),
+ -1);
+ }
+ /* We have timed out without handling an event, break out of loop */
+ if(ret == 0) break;
+ }
+
+ return 0;
+}
+
+int
+ACE_TMAIN (int argc, ACE_TCHAR *argv[])
+{
+ // Estabish call backs and socket names.
+
+ port1 = argc > 1 ? ACE_OS::atoi (argv[1]) : ACE_DEFAULT_SERVER_PORT;
+
+ if(argc < 3)
+ {
+ run_test (port1);
+ }
+ else{
+ ACE_DEBUG((LM_DEBUG, "\nUsage:\n %s [port number]\n", argv[0]));
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/ACE/examples/QOS/Makefile.am b/ACE/examples/QOS/Makefile.am
new file mode 100644
index 00000000000..7b2d8a15844
--- /dev/null
+++ b/ACE/examples/QOS/Makefile.am
@@ -0,0 +1,16 @@
+## Process this file with automake to create Makefile.in
+##
+## $Id$
+##
+## This file was generated by MPC. Any changes made directly to
+## this file will be lost the next time it is generated.
+##
+## MPC Command:
+## /acebuilds/ACE_wrappers-repository/bin/mwc.pl -include /acebuilds/MPC/config -include /acebuilds/MPC/templates -feature_file /acebuilds/ACE_wrappers-repository/local.features -noreldefs -type automake -exclude build,Kokyu
+
+SUBDIRS = \
+ Change_Receiver_FlowSpec \
+ Change_Sender_TSpec \
+ Diffserv \
+ Simple
+
diff --git a/ACE/examples/QOS/Simple/Fill_ACE_QoS.cpp b/ACE/examples/QOS/Simple/Fill_ACE_QoS.cpp
new file mode 100644
index 00000000000..20c03f40fa6
--- /dev/null
+++ b/ACE/examples/QOS/Simple/Fill_ACE_QoS.cpp
@@ -0,0 +1,99 @@
+// Fill_ACE_QoS.cpp
+// $Id$
+
+#include "Fill_ACE_QoS.h"
+
+ACE_RCSID(QOS, Fill_ACE_QoS,"$Id$")
+
+const iovec Fill_ACE_QoS::iov_ = {0,0};
+
+Fill_ACE_QoS::Fill_ACE_QoS (void)
+{
+ ACE_NEW (this->default_traffic_,
+ ACE_Flow_Spec (ACE_QOS_NOT_SPECIFIED,
+ ACE_QOS_NOT_SPECIFIED,
+ ACE_QOS_NOT_SPECIFIED,
+ ACE_QOS_NOT_SPECIFIED,
+ ACE_QOS_NOT_SPECIFIED,
+ ACE_SERVICETYPE_NOTRAFFIC,
+ ACE_QOS_NOT_SPECIFIED,
+ ACE_QOS_NOT_SPECIFIED,
+ 25,
+ 1));
+}
+
+// destructor.
+Fill_ACE_QoS::~Fill_ACE_QoS (void)
+{}
+
+int
+Fill_ACE_QoS::fill_simplex_receiver_qos (ACE_QoS &ace_qos,
+ const ACE_CString &recv_flow_name)
+{
+ ACE_Flow_Spec *recv_flow_spec = 0;
+
+ if (this->map ().find (recv_flow_name, recv_flow_spec) != 0)
+ ACE_ERROR_RETURN ((LM_DEBUG,
+ "Unable to find a FlowSpec with name %s",
+ recv_flow_name.c_str ()),
+ -1);
+ ace_qos.receiving_flowspec (recv_flow_spec);
+ ace_qos.sending_flowspec ((this->default_traffic_));
+ ace_qos.provider_specific (Fill_ACE_QoS::iov_);
+
+ return 0;
+}
+
+
+int
+Fill_ACE_QoS::fill_simplex_sender_qos (ACE_QoS &ace_qos,
+ const ACE_CString &send_flow_name)
+{
+ ACE_Flow_Spec *send_flow_spec = 0;
+
+ if (this->map ().find (send_flow_name, send_flow_spec) != 0)
+ ACE_ERROR_RETURN ((LM_DEBUG,
+ "Unable to find a FlowSpec with name %s",
+ send_flow_name.c_str ()),
+ -1);
+
+ ace_qos.receiving_flowspec ((this->default_traffic_));
+ ace_qos.sending_flowspec (send_flow_spec);
+ ace_qos.provider_specific (Fill_ACE_QoS::iov_);
+
+ return 0;
+}
+
+int
+Fill_ACE_QoS::fill_duplex_qos (ACE_QoS &ace_qos,
+ const ACE_CString &recv_flow_name,
+ const ACE_CString &send_flow_name)
+{
+ ACE_Flow_Spec *send_flow_spec = 0;
+ ACE_Flow_Spec *recv_flow_spec = 0;
+
+ if (this->map ().find (recv_flow_name, recv_flow_spec) != 0)
+ ACE_ERROR_RETURN ((LM_DEBUG,
+ "Unable to find a FlowSpec with name %s",
+ recv_flow_name.c_str ()),
+ -1);
+
+ if (this->map ().find (send_flow_name, send_flow_spec) != 0)
+ ACE_ERROR_RETURN ((LM_DEBUG,
+ "Unable to find a FlowSpec with name %s",
+ send_flow_name.c_str ()),
+ -1);
+
+ ace_qos.receiving_flowspec (recv_flow_spec);
+ ace_qos.sending_flowspec (send_flow_spec);
+ ace_qos.provider_specific (Fill_ACE_QoS::iov_);
+
+ return 0;
+}
+
+Fill_ACE_QoS::FLOW_SPEC_HASH_MAP&
+Fill_ACE_QoS::map (void)
+{
+ return this->flow_spec_map_;
+}
+
diff --git a/ACE/examples/QOS/Simple/Fill_ACE_QoS.h b/ACE/examples/QOS/Simple/Fill_ACE_QoS.h
new file mode 100644
index 00000000000..281b9beb876
--- /dev/null
+++ b/ACE/examples/QOS/Simple/Fill_ACE_QoS.h
@@ -0,0 +1,75 @@
+/* -*- C++ -*- */
+// $Id$
+
+// ============================================================================
+//
+// = LIBRARY
+// ACE_wrappers/examples/QOS
+//
+// = FILENAME
+// Fill_ACE_QoS.h
+//
+// = AUTHOR
+// Vishal Kachroo <vishal@cs.wustl.edu>
+//
+// ============================================================================
+
+#ifndef FILL_ACE_QOS_H
+#define FILL_ACE_QOS_H
+
+#include "ace/SString.h"
+#include "ace/Hash_Map_Manager.h"
+#include "ace/ACE.h"
+#include "ace/Null_Mutex.h"
+#include "ace/OS_QoS.h"
+
+class Fill_ACE_QoS
+{
+ // TITLE
+ // This class helps users to add new flow specs and provides
+ // utility functions for filling up the flow specs for simplex/duplex
+ // sessions.
+
+public:
+ typedef ACE_Hash_Map_Manager <ACE_CString, ACE_Flow_Spec *, ACE_Null_Mutex> FLOW_SPEC_HASH_MAP;
+
+ //Initialization and termination methods.
+ Fill_ACE_QoS (void);
+ // constructor.
+
+ ~Fill_ACE_QoS (void);
+ // destructor.
+
+ int fill_simplex_receiver_qos (ACE_QoS &ace_qos,
+ const ACE_CString &recv_flow_name);
+ // To be used by receivers. Fills the receiver qos and sets the
+ // sender qos to NO_TRAFFIC.
+
+ int fill_simplex_sender_qos (ACE_QoS &ace_qos,
+ const ACE_CString &send_flow_name);
+ // To be used by senders. Fills the sender qos and sets the receiver
+ // qos to NO_TRAFFIC.
+
+ int fill_duplex_qos (ACE_QoS &ace_qos,
+ const ACE_CString &recv_flow_name,
+ const ACE_CString &send_flow_name);
+ // To be used by applications that wish to be both receivers and
+ // senders.
+
+ FLOW_SPEC_HASH_MAP& map (void);
+ // Returns the hash map of flowspecs indexed by flowspec name.
+
+private:
+
+ // The Service Provider is currently set to NULL for all ACE_QoS.
+ static const iovec iov_;
+
+ // A NO_TRAFFIC flow spec. Senders set the receiving qos to this
+ // while the receivers set the sending qos to this.
+ ACE_Flow_Spec *default_traffic_;
+
+ // A list of flowspecs indexed by the flowspec name.
+ FLOW_SPEC_HASH_MAP flow_spec_map_;
+};
+
+#endif /* FILL_ACE_QOS_H */
diff --git a/ACE/examples/QOS/Simple/FlowSpec_Dbase.h b/ACE/examples/QOS/Simple/FlowSpec_Dbase.h
new file mode 100644
index 00000000000..fc382048c13
--- /dev/null
+++ b/ACE/examples/QOS/Simple/FlowSpec_Dbase.h
@@ -0,0 +1,52 @@
+/* -*- C++ -*- */
+//$Id$
+
+// ============================================================================
+//
+// = LIBRARY
+// ACE_wrappers/examples/QOS
+//
+// = FILENAME
+// FlowSpec_Dbase.h
+//
+// = AUTHOR
+// Vishal Kachroo <vishal@cs.wustl.edu>
+//
+// ============================================================================
+
+#ifndef FLOWSPEC_DBASE_H
+#define FLOWSPEC_DBASE_H
+
+// This file contains the different FlowSpecs that the QoS enabled
+// application uses. Its a good idea to list them all here so the
+// application code is clean.
+
+ACE_Flow_Spec notraffic (ACE_QOS_NOT_SPECIFIED,
+ ACE_QOS_NOT_SPECIFIED,
+ ACE_QOS_NOT_SPECIFIED,
+ ACE_QOS_NOT_SPECIFIED,
+ ACE_QOS_NOT_SPECIFIED,
+ ACE_SERVICETYPE_NOTRAFFIC,
+ ACE_QOS_NOT_SPECIFIED,
+ ACE_QOS_NOT_SPECIFIED,
+ 25,
+ 1);
+
+ACE_Flow_Spec g711 (9200,
+ 708,
+ 18400,
+ 0,
+ 0,
+ ACE_SERVICETYPE_CONTROLLEDLOAD,
+ 368,
+ 368,
+ 25,
+ 1);
+
+// The default session address is macarena.cs.wustl.edu. I am using macarena
+// as my receiver for testing.
+#define DEFAULT_QOS_SESSION_MACHINE "128.252.165.127"
+#define DEFAULT_QOS_SESSION_PORT 8001
+
+#endif /* FLOWSPEC_DBASE_H */
+
diff --git a/ACE/examples/QOS/Simple/Makefile.am b/ACE/examples/QOS/Simple/Makefile.am
new file mode 100644
index 00000000000..d86d7cd43eb
--- /dev/null
+++ b/ACE/examples/QOS/Simple/Makefile.am
@@ -0,0 +1,76 @@
+## Process this file with automake to create Makefile.in
+##
+## $Id$
+##
+## This file was generated by MPC. Any changes made directly to
+## this file will be lost the next time it is generated.
+##
+## MPC Command:
+## /acebuilds/ACE_wrappers-repository/bin/mwc.pl -include /acebuilds/MPC/config -include /acebuilds/MPC/templates -feature_file /acebuilds/ACE_wrappers-repository/local.features -noreldefs -type automake -exclude build,Kokyu
+
+ACE_BUILDDIR = $(top_builddir)
+ACE_ROOT = $(top_srcdir)
+
+noinst_PROGRAMS =
+
+## Makefile.QOS_Simple_Receiver.am
+
+if BUILD_QOS
+noinst_PROGRAMS += receiver
+
+receiver_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR) \
+ -DACE_HAS_QOS
+
+receiver_SOURCES = \
+ Fill_ACE_QoS.cpp \
+ QoS_Signal_Handler.cpp \
+ QoS_Util.cpp \
+ Receiver_QoS_Event_Handler.cpp \
+ receiver.cpp \
+ Fill_ACE_QoS.h \
+ QoS_Signal_Handler.h \
+ QoS_Util.h \
+ Receiver_QoS_Event_Handler.h
+
+receiver_LDADD = \
+ $(ACE_BUILDDIR)/ace/QoS/libACE_QoS.la \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+endif BUILD_QOS
+
+## Makefile.QOS_Simple_Sender.am
+
+if BUILD_QOS
+noinst_PROGRAMS += sender
+
+sender_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR) \
+ -DACE_HAS_QOS
+
+sender_SOURCES = \
+ Fill_ACE_QoS.cpp \
+ QoS_Signal_Handler.cpp \
+ QoS_Util.cpp \
+ Sender_QoS_Event_Handler.cpp \
+ sender.cpp \
+ Fill_ACE_QoS.h \
+ QoS_Signal_Handler.h \
+ QoS_Util.h \
+ Sender_QoS_Event_Handler.h
+
+sender_LDADD = \
+ $(ACE_BUILDDIR)/ace/QoS/libACE_QoS.la \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+endif BUILD_QOS
+
+## Clean up template repositories, etc.
+clean-local:
+ -rm -f *~ *.bak *.rpo *.sym lib*.*_pure_* core core.*
+ -rm -f gcctemp.c gcctemp so_locations *.ics
+ -rm -rf cxx_repository ptrepository ti_files
+ -rm -rf templateregistry ir.out
+ -rm -rf ptrepository SunWS_cache Templates.DB
diff --git a/ACE/examples/QOS/Simple/QOS_Simple.mpc b/ACE/examples/QOS/Simple/QOS_Simple.mpc
new file mode 100644
index 00000000000..9767bd6fdb9
--- /dev/null
+++ b/ACE/examples/QOS/Simple/QOS_Simple.mpc
@@ -0,0 +1,25 @@
+// -*- MPC -*-
+// $Id$
+
+project(*receiver) : aceexe, qos {
+ exename = receiver
+ requires += qos
+ Source_Files {
+ Fill_ACE_QoS.cpp
+ QoS_Signal_Handler.cpp
+ QoS_Util.cpp
+ receiver.cpp
+ Receiver_QoS_Event_Handler.cpp
+ }
+}
+project(*sender) : aceexe, qos {
+ exename = sender
+ requires += qos
+ Source_Files {
+ Fill_ACE_QoS.cpp
+ QoS_Signal_Handler.cpp
+ QoS_Util.cpp
+ sender.cpp
+ Sender_QoS_Event_Handler.cpp
+ }
+}
diff --git a/ACE/examples/QOS/Simple/QoS_Signal_Handler.cpp b/ACE/examples/QOS/Simple/QoS_Signal_Handler.cpp
new file mode 100644
index 00000000000..a0533bacdbc
--- /dev/null
+++ b/ACE/examples/QOS/Simple/QoS_Signal_Handler.cpp
@@ -0,0 +1,40 @@
+// QoS_Signal_Handler.cpp
+// $Id$
+
+#include "ace/Log_Msg.h"
+#include "QoS_Signal_Handler.h"
+
+ACE_RCSID(QOS, QoS_Signal_Handler,"$Id$")
+
+// constructor.
+QoS_Signal_Handler::QoS_Signal_Handler (ACE_QoS_Session *qos_session)
+ : qos_session_ (qos_session)
+{
+}
+
+// Releases the QoS sessions gracefully.
+int
+QoS_Signal_Handler::handle_signal (int signum, siginfo_t *, ucontext_t*)
+{
+
+ ACE_DEBUG ((LM_DEBUG,
+ "QoS_Signal_Handler::handle_signal\n"));
+
+ if (signum == SIGINT)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ "QoS_Signal_Handler::handle_signal SIGINT called\n"));
+ if (this->qos_session_->close () == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Unable to close the QoS session.\n"),
+ -1);
+ else
+ ACE_DEBUG ((LM_DEBUG,
+ "QoS Session with id %d closed successfully.\n",
+ this->qos_session_->session_id ()));
+ }
+ else
+ ACE_DEBUG ((LM_DEBUG,
+ "A signal other than SIGINT received.\nIgnoring.\n"));
+ return 0;
+}
diff --git a/ACE/examples/QOS/Simple/QoS_Signal_Handler.h b/ACE/examples/QOS/Simple/QoS_Signal_Handler.h
new file mode 100644
index 00000000000..35b9f3a19e7
--- /dev/null
+++ b/ACE/examples/QOS/Simple/QoS_Signal_Handler.h
@@ -0,0 +1,45 @@
+/* -*- C++ -*- */
+// $Id$
+
+// =====================================================================
+//
+// = LIBRARY
+// ACE_wrappers/examples/QOS
+//
+// = FILENAME
+// QoS_Signal_Handler.h
+//
+// = AUTHOR
+// Vishal Kachroo <vishal@cs.wustl.edu>
+//
+// =====================================================================
+
+#ifndef QOS_SIGNAL_HANDLER_H
+#define QOS_SIGNAL_HANDLER_H
+
+#include "ace/Event_Handler.h"
+#include "ace/QoS/QoS_Session.h"
+
+class QoS_Signal_Handler : public ACE_Event_Handler
+{
+ // TITLE
+ // This class Handles the SIGINT signal through the Reactor.
+ // Useful to gracefully release QoS sessions.
+
+public:
+
+ QoS_Signal_Handler (ACE_QoS_Session *qos_session);
+ // constructor.
+
+ int handle_signal(int signum, siginfo_t*,ucontext_t*);
+ // Override this method to implement graceful shutdown.
+
+private:
+
+ ACE_QoS_Session *qos_session_;
+ // Session to be gracefully shutdown.
+
+};
+
+#endif /* QOS_SIGNAL_HANDLER_H */
+
diff --git a/ACE/examples/QOS/Simple/QoS_Util.cpp b/ACE/examples/QOS/Simple/QoS_Util.cpp
new file mode 100644
index 00000000000..0ef3b353248
--- /dev/null
+++ b/ACE/examples/QOS/Simple/QoS_Util.cpp
@@ -0,0 +1,122 @@
+// QoS_Session_Impl.cpp
+// $Id$
+
+#define SENDER_PORT 10001
+
+#include "ace/Log_Msg.h"
+#include "ace/Get_Opt.h"
+#include "QoS_Util.h"
+#include "ace/OS_NS_strings.h"
+
+ACE_RCSID(QOS, QoS_Util,"$Id$")
+
+// constructor.
+QoS_Util::QoS_Util (int argc,
+ ACE_TCHAR *argv[])
+ : argc_ (argc),
+ argv_ (argv),
+ source_port_ (SENDER_PORT),
+ protocol_ (IPPROTO_UDP),
+ multicast_flag_ (0)
+{
+ ACE_NEW (this->mult_session_addr_,
+ ACE_INET_Addr (ACE_DEFAULT_MULTICAST_PORT));
+
+ ACE_NEW (this->dest_addr_,
+ ACE_INET_Addr (ACE_DEFAULT_SERVER_PORT));
+}
+
+// destructor.
+QoS_Util::~QoS_Util (void)
+{
+ delete this->mult_session_addr_;
+ delete this->dest_addr_;
+}
+
+int
+QoS_Util::parse_args (void)
+{
+ ACE_Get_Opt get_opts (this->argc_, this->argv_, ACE_TEXT("m:n:p:P:c"));
+ int c = 0;
+
+ while ((c = get_opts ()) != -1)
+ switch (c)
+ {
+ case 'm': // multicast session address.
+ this->multicast_flag_ = 1;
+ this->mult_session_addr_->set (get_opts.opt_arg ());
+ break;
+ case 'n': // to be used by Senders only to specify the destination.
+ this->dest_addr_->set (get_opts.opt_arg ());
+ break;
+ case 'p': // protocol.
+ if (ACE_OS::strcasecmp (get_opts.opt_arg (), ACE_TEXT("tcp")) == 0)
+ this->protocol_ = IPPROTO_TCP;
+ else
+ if (ACE_OS::strcasecmp (get_opts.opt_arg (), ACE_TEXT("udp")) == 0)
+ this->protocol_ = IPPROTO_UDP;
+ else
+ ACE_DEBUG ((LM_DEBUG,
+ "Unknown protocol specified\n"
+ "UDP assumed\n"));
+ break;
+ case 'P': // sender source port.
+ this->source_port_ = ACE_OS::atoi (get_opts.opt_arg ());
+ break;
+ case 'h': // display help for different options.
+ default:
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "usage: %s"
+ " [-m host:port] QoS multicast session address"
+ " Overides the receiver address specified in the -n option"
+ " [-n host:port] Use for a unicast sender. "
+ " Follow by receiver addr"
+ " [-p tcp|udp] specify protocol to be used"
+ " [-P port] source sender port"
+ " [-h] <help>"
+ "\n",
+ argv_ [0]),
+ -1);
+ }
+
+ // If multicast address is specified then ignore the unicast sender
+ // destination address and force the protocol to be UDP.
+ if (this->multicast_flag_ == 1)
+ {
+ this->dest_addr_ = this->mult_session_addr_;
+ this->protocol_ = IPPROTO_UDP;
+ }
+
+ // Indicates successful parsing of command line.
+ return 0;
+}
+
+ACE_INET_Addr *
+QoS_Util::mult_session_addr (void) const
+{
+ return this->mult_session_addr_;
+}
+
+ACE_INET_Addr *
+QoS_Util::dest_addr (void) const
+{
+ return this->dest_addr_;
+}
+
+u_short
+QoS_Util::source_port (void) const
+{
+ return this->source_port_;
+}
+
+ACE_Protocol_ID
+QoS_Util::protocol (void) const
+{
+ return this->protocol_;
+}
+
+int
+QoS_Util::multicast_flag (void) const
+{
+ return this->multicast_flag_;
+}
diff --git a/ACE/examples/QOS/Simple/QoS_Util.h b/ACE/examples/QOS/Simple/QoS_Util.h
new file mode 100644
index 00000000000..ae347de68f6
--- /dev/null
+++ b/ACE/examples/QOS/Simple/QoS_Util.h
@@ -0,0 +1,75 @@
+/* -*- C++ -*- */
+// $Id$
+
+// =====================================================================
+//
+// = LIBRARY
+// ACE_wrappers/examples/QOS
+//
+// = FILENAME
+// QoS_Util.h
+//
+// = AUTHOR
+// Vishal Kachroo <vishal@cs.wustl.edu>
+//
+// =====================================================================
+
+#ifndef QOS_UTIL_H
+#define QOS_UTIL_H
+
+#include "ace/INET_Addr.h"
+#include "ace/QoS/QoS_Session.h"
+
+class QoS_Util
+{
+ // = TITLE
+ // This class provides the utility functions like parse_args ()
+ // required by a QoS enabled application.
+
+public:
+
+ // constructor.
+ QoS_Util (int argc, ACE_TCHAR *argv[]);
+
+ // destructor.
+ ~QoS_Util (void);
+
+ // Parse command-line arguments.
+ int parse_args (void);
+
+ // GET methods.
+ ACE_INET_Addr *mult_session_addr (void) const;
+
+ ACE_INET_Addr *dest_addr (void) const;
+
+ u_short source_port (void) const;
+
+ ACE_Protocol_ID protocol (void) const;
+
+ int multicast_flag (void) const;
+
+private:
+
+ // Command line arguments.
+ int argc_;
+ ACE_TCHAR **argv_;
+
+ // Multicast session address.
+ ACE_INET_Addr *mult_session_addr_;
+
+ // Unicast destination address of the receiver.
+ ACE_INET_Addr *dest_addr_;
+
+ // Source port for the sender.
+ u_short source_port_;
+
+ // Protocol.
+ ACE_Protocol_ID protocol_;
+
+ // Multicast Flag.
+ int multicast_flag_;
+
+};
+
+#endif /* QOS_UTIL_H */
+
diff --git a/ACE/examples/QOS/Simple/README b/ACE/examples/QOS/Simple/README
new file mode 100644
index 00000000000..13255842932
--- /dev/null
+++ b/ACE/examples/QOS/Simple/README
@@ -0,0 +1,142 @@
+//$Id$
+
+A Regression test for ACE QoS features.
+---------------------------------------
+
+This test implements a simple Receiver-Sender program that ensures
+Quality of Service (QoS) guarantees on the underlying network before
+transmitting data. The program tests the ACE QoS APIs/features. The
+test works for Winsock2 APIs on Win2K as well as RAPI on Solaris.
+
+
+------------------------------------------------------------------------
+WIN2K :
+
+Build Requirements :
+--------------------
+1. Two Win2K machines.
+2. June98 Platform SDK or later.
+3. Link with ws2_32.lib
+
+The test consists of a receiver and a sender.
+
+ The sender is started first (though it is not mandatory) as :
+
+ sender -m merengue.cs.wustl.edu:9091 -P 10004
+
+ -m: specifies the multicast session address that both client and
+ server subscribe to for QoS events.
+
+ -p: Protocol to be used. Could be udp or tcp. Default is udp.
+
+ -P: Sender source port. If not specified, DEFAULT_SOURCE_SENDER_PORT
+ (10001) will be used.
+
+ -h: Displays the help on various options.
+
+The sample Sender is started next as :
+
+ receiver -m merengue.cs.wustl.edu:9091
+
+ -m: specifies the multicast session address that both client and
+ server subscribe to for QoS events.
+
+ -n: Option to be used by senders only to specify the destination
+ address. This option is overriden if a multicast address is also
+ specified through the -m option.
+
+ -p: Protocol to be used. Could be udp or tcp. Default is udp.
+
+ -P: Sender source port. If not specified, DEFAULT_SOURCE_SENDER_PORT
+ (10001) will be used.
+
+ -h: Displays the help on various options.
+
+On Win2K the user must have administrative access to the machine to
+run this program. It seems to be a pre-requisite to opening QoS
+sockets.
+
+The sender and receiver should be run on different Win2K machines.
+
+The test demonstrates how to GQOS enable an application using the ACE QoS APIs.
+It concentrates on the use of various ACE QoS APIs and their correctness.
+
+-------------------------------------------------------------------------------
+
+RAPI :
+
+0. The $ACE_ROOT/include/makeinclude/platform_macros.GNU should include the
+following :
+
+include /project/doc/vishal/ACE_wrappers/include/makeinclude/<appropriate platform macros file eg.platform_sunos5_sunc++.GNU>
+PLATFORM_RAPI_CPPFLAGS += -I/project/doc/vishal/rapi/rel4.2a4/rsvpd/
+PLATFORM_RAPI_LIBS += -lrsvp
+PLATFORM_RAPI_LDFLAGS += -L/project/doc/vishal/rapi/rel4.2a4/rsvpd/
+
+assuming that RAPI library is installed in /project/doc/vishal/rapi/rel4.2a4/
+
+1. Compile ACE with
+
+ make rapi=1
+
+2. Run the RSVP Daemon on two machines: (merengue.cs and macarena.cs)
+
+ /project/doc/vishal/rapi/rel4.2a4/rsvpd/rsvpd -D
+
+ The current version of the daemon comes with an inbuilt rtap
+ application to test the various reservation commands and RAPI APIs.
+
+ Typical values for rtap would be :
+
+ dest udp macarena/5000
+ sender merengue/5000 [ t 2000000 100000 2000000 512 1024 ]
+
+ dest udp macarena/5000
+ reserve wf [ cl 2000000 100000 2000000 512 1024 ]
+
+3. If RTAP runs fine and the daemons show the debug messages about
+ RESV, PATH and other RSVP messages, run the QoS example, making sure
+ that rtap session is released on both machines.
+
+The test consists of a receiver and a sender.
+
+ The sender is started first (though it is not mandatory) as :
+
+ sender -m macarena.cs.wustl.edu:9091 -P 10004
+
+ -m: specifies the multicast session address that both client and
+ server subscribe to for QoS events.
+
+ -p: Protocol to be used. Could be udp or tcp. Default is udp.
+
+ -P: Sender source port. If not specified, DEFAULT_SOURCE_SENDER_PORT
+ (10001) will be used.
+
+ -h: Displays the help on various options.
+
+The sample Sender is started next as :
+
+ receiver -m macarena.cs.wustl.edu:9091
+
+ -m: specifies the multicast session address that both client and
+ server subscribe to for QoS events.
+
+ -n: Option to be used by senders only to specify the destination
+ address. This option is overriden if a multicast address is also
+ specified through the -m option.
+
+ -p: Protocol to be used. Could be udp or tcp. Default is udp.
+
+ -P: Sender source port. If not specified, DEFAULT_SOURCE_SENDER_PORT
+ (10001) will be used.
+
+ -h: Displays the help on various options.
+
+-------------------------------------------------------------------------------
+
+If you run into any problems with this test please contact Vishal
+Kachroo <vishal@cs.wustl.edu>.
+
+This README last updated on 20th July, 2000.
+
+-------------------------------------------------------------------------------
diff --git a/ACE/examples/QOS/Simple/Receiver_QoS_Event_Handler.cpp b/ACE/examples/QOS/Simple/Receiver_QoS_Event_Handler.cpp
new file mode 100644
index 00000000000..69258313420
--- /dev/null
+++ b/ACE/examples/QOS/Simple/Receiver_QoS_Event_Handler.cpp
@@ -0,0 +1,137 @@
+/* -*- C++ -*- */
+// $Id$
+
+// ============================================================================
+//
+// = LIBRARY
+// ACE_wrappers/examples/QOS
+//
+// = FILENAME
+// Receiver_QoS_Event_Handler.cpp
+//
+// = AUTHOR
+// Vishal Kachroo <vishal@cs.wustl.edu>
+//
+// ============================================================================
+
+#include "Receiver_QoS_Event_Handler.h"
+#include "ace/Log_Msg.h"
+#include "ace/OS_NS_string.h"
+
+// Constructor.
+Receiver_QoS_Event_Handler::Receiver_QoS_Event_Handler (void)
+{
+}
+
+Receiver_QoS_Event_Handler::Receiver_QoS_Event_Handler (const ACE_SOCK_Dgram_Mcast_QoS
+ &dgram_mcast_qos,
+ ACE_QoS_Session *qos_session)
+ : dgram_mcast_qos_ (dgram_mcast_qos),
+ qos_session_ (qos_session)
+{
+}
+
+// Destructor.
+Receiver_QoS_Event_Handler::~Receiver_QoS_Event_Handler (void)
+{
+}
+
+// Return the handle of the Dgram_Mcast. This method is called
+// internally by the reactor.
+ACE_HANDLE
+Receiver_QoS_Event_Handler::get_handle (void) const
+{
+ return this->dgram_mcast_qos_.get_handle ();
+}
+
+// Called when there is a READ activity on the dgram_mcast_qos handle.
+int
+Receiver_QoS_Event_Handler::handle_input (ACE_HANDLE)
+{
+ char buf[BUFSIZ];
+
+ iovec iov;
+ iov.iov_base = buf;
+ iov.iov_len = BUFSIZ;
+
+ ACE_OS::memset (iov.iov_base,
+ 0,
+ BUFSIZ);
+
+ ACE_DEBUG ((LM_DEBUG,
+ "Inside handle_input () of Receiver_QoS_Event_Handler ()\n"));
+
+ // Receive message from multicast group.
+ ssize_t result =
+ this->dgram_mcast_qos_.recv (&iov,
+ 1,
+ this->remote_addr_);
+
+ if (result != -1)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ "Message Received : %s",
+ iov.iov_base));
+ return 0;
+ }
+ else
+ return -1;
+}
+
+// Called when there is a QoS Event.
+int
+Receiver_QoS_Event_Handler::handle_qos (ACE_HANDLE fd)
+{
+ ACE_UNUSED_ARG (fd);
+
+ ACE_DEBUG ((LM_DEBUG,
+ "\nReceived a QOS event. Inside handle_qos ()\n"));
+
+ // We have received an RSVP event. The following update_qos () call
+ // calls rapi_dispatch () in case of RAPI and WSAIoctl (GET_QOS) in
+ // case of W2K. It then does the QoS parameter translation and updates
+ // the QoS session object with the latest QoS. This call replaces the
+ // direct call that was being made to WSAIoctl (GET_QOS) here for the
+ // Win2K example.
+
+ if (this->qos_session_->update_qos () == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Error in updating QoS\n"),
+ -1);
+ else
+ ACE_DEBUG ((LM_DEBUG,
+ " Updating QOS succeeds.\n"));
+
+ // Now proactively query the QoS object for QoS.
+ ACE_QoS ace_get_qos = this->qos_session_->qos ();
+
+ ACE_DEBUG ((LM_DEBUG,
+ "\nReceiving Flowspec :\t\t\tSending Flowspec :\n\n"
+ "\tToken Rate = %d\t\t\tToken Rate = %d\n"
+ "\tToken Bucket Size = %d\t\t\tToken Bucket Size = %d\n"
+ "\tPeak Bandwidth = %d\t\t\tPeak Bandwidth = %d\n"
+ "\tLatency = %d\t\t\t\tLatency = %d\n"
+ "\tDelay Variation = %d\t\t\tDelay Variation = %d\n"
+ "\tService Type = %d\t\t\tService Type = %d\n"
+ "\tMax SDU Size = %d\t\t\tMax SDU Size = %d\n"
+ "\tMinimum Policed Size = %d\t\tMinimum Policed Size = %d\n\n",
+ ace_get_qos.receiving_flowspec ()->token_rate (),
+ ace_get_qos.sending_flowspec ()->token_rate (),
+ ace_get_qos.receiving_flowspec ()->token_bucket_size (),
+ ace_get_qos.sending_flowspec ()->token_bucket_size (),
+ ace_get_qos.receiving_flowspec ()->peak_bandwidth (),
+ ace_get_qos.sending_flowspec ()->peak_bandwidth (),
+ ace_get_qos.receiving_flowspec ()->latency (),
+ ace_get_qos.sending_flowspec ()->latency (),
+ ace_get_qos.receiving_flowspec ()->delay_variation (),
+ ace_get_qos.sending_flowspec ()->delay_variation (),
+ ace_get_qos.receiving_flowspec ()->service_type (),
+ ace_get_qos.sending_flowspec ()->service_type (),
+ ace_get_qos.receiving_flowspec ()->max_sdu_size (),
+ ace_get_qos.sending_flowspec ()->max_sdu_size (),
+ ace_get_qos.receiving_flowspec ()->minimum_policed_size (),
+ ace_get_qos.sending_flowspec ()->minimum_policed_size ()));
+
+ return 0;
+
+}
diff --git a/ACE/examples/QOS/Simple/Receiver_QoS_Event_Handler.h b/ACE/examples/QOS/Simple/Receiver_QoS_Event_Handler.h
new file mode 100644
index 00000000000..874d628e3c1
--- /dev/null
+++ b/ACE/examples/QOS/Simple/Receiver_QoS_Event_Handler.h
@@ -0,0 +1,61 @@
+/* -*- C++ -*- */
+// $Id$
+
+// ============================================================================
+//
+// = LIBRARY
+// ACE_wrappers/examples/QOS
+//
+// = FILENAME
+// Receiver_QoS_Event_Handler.h
+//
+// = AUTHOR
+// Vishal Kachroo <vishal@cs.wustl.edu>
+//
+// ============================================================================
+
+#ifndef RECEIVER_QOS_EVENT_HANDLER_H
+#define RECEIVER_QOS_EVENT_HANDLER_H
+
+#include "ace/Reactor.h"
+#include "ace/INET_Addr.h"
+#include "ace/Event_Handler.h"
+#include "ace/QoS/QoS_Session.h"
+#include "ace/QoS/SOCK_Dgram_Mcast_QoS.h"
+
+ACE_RCSID(Receiver_QoS_Event_Handler, Receiver_QoS_Event_Handler, "$Id$")
+
+ class Receiver_QoS_Event_Handler : public ACE_Event_Handler
+ {
+ public:
+ // = Initialization and Termination methods.
+ Receiver_QoS_Event_Handler (void);
+ // Constructor.
+
+ Receiver_QoS_Event_Handler::Receiver_QoS_Event_Handler (const ACE_SOCK_Dgram_Mcast_QoS &dgram_mcast_qos,
+ ACE_QoS_Session *qos_session);
+ // Constructor.
+
+ ~Receiver_QoS_Event_Handler (void);
+ // Destructor.
+
+ virtual ACE_HANDLE get_handle (void) const;
+ // Override this to return the handle of the Dgram_Mcast
+ // that we are using.
+
+ virtual int handle_input (ACE_HANDLE fd);
+ // Handles a READ event.
+
+ virtual int handle_qos (ACE_HANDLE fd);
+ // Handles a QoS event.
+
+ private:
+ ACE_SOCK_Dgram_Mcast_QoS dgram_mcast_qos_;
+ ACE_QoS_Session *qos_session_;
+ ACE_INET_Addr remote_addr_;
+ };
+
+#endif /* RECEIVER_QOS_EVENT_HANDLER_H */
+
+
+
diff --git a/ACE/examples/QOS/Simple/Sender_QoS_Event_Handler.cpp b/ACE/examples/QOS/Simple/Sender_QoS_Event_Handler.cpp
new file mode 100644
index 00000000000..5ee4ccf0f8e
--- /dev/null
+++ b/ACE/examples/QOS/Simple/Sender_QoS_Event_Handler.cpp
@@ -0,0 +1,144 @@
+/* -*- C++ -*- */
+// $Id$
+
+// ============================================================================
+//
+// = LIBRARY
+// ACE_wrappers/examples/QOS
+//
+// = FILENAME
+// Sender_QoS_Event_Handler.cpp
+//
+// = AUTHOR
+// Vishal Kachroo <vishal@cs.wustl.edu>
+//
+// ============================================================================
+
+#include "Sender_QoS_Event_Handler.h"
+#include "ace/Log_Msg.h"
+#include "ace/OS_NS_string.h"
+
+// Constructor.
+Sender_QoS_Event_Handler::Sender_QoS_Event_Handler (void)
+{
+}
+
+// Constructor.
+Sender_QoS_Event_Handler::Sender_QoS_Event_Handler (const ACE_SOCK_Dgram_Mcast_QoS
+ &dgram_mcast_qos,
+ ACE_QoS_Session *qos_session)
+ : dgram_mcast_qos_ (dgram_mcast_qos),
+ qos_session_ (qos_session)
+{
+}
+
+// Destructor.
+Sender_QoS_Event_Handler::~Sender_QoS_Event_Handler (void)
+{
+}
+
+// Return the handle of the Dgram_Mcast. This method is called
+// internally by the reactor.
+
+ACE_HANDLE
+Sender_QoS_Event_Handler::get_handle (void) const
+{
+ return this->dgram_mcast_qos_.get_handle ();
+}
+
+// Handle the QoS Event. In this case send data to the receiver
+// using WSASendTo() that uses overlapped I/O.
+
+int
+Sender_QoS_Event_Handler::handle_qos (ACE_HANDLE)
+{
+ ACE_DEBUG ((LM_DEBUG,
+ "\nReceived a QOS event. Inside handle_qos ()\n"));
+
+ // We have received an RSVP event. The following update_qos () call
+ // calls rapi_dispatch () in case of RAPI and WSAIoctl (GET_QOS) in
+ // case of W2K. It then does the QoS parameter translation and updates
+ // the QoS session object with the latest QoS. This call replaces the
+ // direct call that was being made to WSAIoctl (GET_QOS) here for the
+ // Win2K example.
+
+ if (this->qos_session_->update_qos () == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Error in updating QoS\n"),
+ -1);
+ else
+ ACE_DEBUG ((LM_DEBUG,
+ " Updating QOS succeeds.\n"));
+
+ // Now proactively query the QoS object for QoS.
+ ACE_QoS ace_get_qos = this->qos_session_->qos ();
+
+ ACE_DEBUG ((LM_DEBUG,
+ "\nReceiving Flowspec :\t\t\tSending Flowspec :\n\n"
+ "\tToken Rate = %d\t\t\tToken Rate = %d\n"
+ "\tToken Bucket Size = %d\t\t\tToken Bucket Size = %d\n"
+ "\tPeak Bandwidth = %d\t\t\tPeak Bandwidth = %d\n"
+ "\tLatency = %d\t\t\t\tLatency = %d\n"
+ "\tDelay Variation = %d\t\t\tDelay Variation = %d\n"
+ "\tService Type = %d\t\t\tService Type = %d\n"
+ "\tMax SDU Size = %d\t\t\tMax SDU Size = %d\n"
+ "\tMinimum Policed Size = %d\t\tMinimum Policed Size = %d\n\n",
+ ace_get_qos.receiving_flowspec ()->token_rate (),
+ ace_get_qos.sending_flowspec ()->token_rate (),
+ ace_get_qos.receiving_flowspec ()->token_bucket_size (),
+ ace_get_qos.sending_flowspec ()->token_bucket_size (),
+ ace_get_qos.receiving_flowspec ()->peak_bandwidth (),
+ ace_get_qos.sending_flowspec ()->peak_bandwidth (),
+ ace_get_qos.receiving_flowspec ()->latency (),
+ ace_get_qos.sending_flowspec ()->latency (),
+ ace_get_qos.receiving_flowspec ()->delay_variation (),
+ ace_get_qos.sending_flowspec ()->delay_variation (),
+ ace_get_qos.receiving_flowspec ()->service_type (),
+ ace_get_qos.sending_flowspec ()->service_type (),
+ ace_get_qos.receiving_flowspec ()->max_sdu_size (),
+ ace_get_qos.sending_flowspec ()->max_sdu_size (),
+ ace_get_qos.receiving_flowspec ()->minimum_policed_size (),
+ ace_get_qos.sending_flowspec ()->minimum_policed_size ()));
+
+ // This is SPECIFIC TO WIN2K and should be done in the qos_update function.
+
+// ACE_QoS ace_get_qos;
+// u_long dwBytes;
+
+// if (ACE_OS::ioctl (this->dgram_mcast_qos_.get_handle (),
+// ACE_SIO_GET_QOS,
+// ace_get_qos,
+// &dwBytes) == -1)
+// ACE_ERROR ((LM_ERROR,
+// "Error in Qos get ACE_OS::ioctl ()\n"
+// "Bytes Returned = %d\n",
+// dwBytes));
+// else
+// ACE_DEBUG ((LM_DEBUG,
+// "Getting QOS using ACE_OS::ioctl () succeeds.\n"));
+
+ char* msg = "Hello sent on a QoS enabled session !!\n";
+ iovec iov[1];
+ iov[0].iov_base = msg;
+ iov[0].iov_len = ACE_OS::strlen(msg);
+
+ size_t bytes_sent = 0;
+
+ // Send "Hello" to the QoS session address to which the receiver has
+ // subscribed.
+ if (this->dgram_mcast_qos_.send (iov,
+ 1,
+ bytes_sent,
+ 0,
+ this->qos_session_->dest_addr (),
+ 0,
+ 0) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Error in dgram_mcast.send ()\n"),
+ -1);
+ else
+ ACE_DEBUG ((LM_DEBUG,
+ "Using ACE_OS::sendto () : Bytes sent : %d",
+ bytes_sent));
+ return 0;
+}
diff --git a/ACE/examples/QOS/Simple/Sender_QoS_Event_Handler.h b/ACE/examples/QOS/Simple/Sender_QoS_Event_Handler.h
new file mode 100644
index 00000000000..b691bbd0615
--- /dev/null
+++ b/ACE/examples/QOS/Simple/Sender_QoS_Event_Handler.h
@@ -0,0 +1,61 @@
+/* -*- C++ -*- */
+// $Id$
+
+// ============================================================================
+//
+// = LIBRARY
+// ACE_wrappers/examples/QOS
+//
+// = FILENAME
+// Sender_QoS_Event_Handler.h
+//
+// = AUTHOR
+// Vishal Kachroo <vishal@cs.wustl.edu>
+//
+// ============================================================================
+
+#ifndef SENDER_QOS_EVENT_HANDLER_H
+#define SENDER_QOS_EVENT_HANDLER_H
+
+#include "ace/Event_Handler.h"
+#include "ace/Reactor.h"
+#include "ace/INET_Addr.h"
+#include "ace/QoS/SOCK_Dgram_Mcast_QoS.h"
+#include "ace/QoS/QoS_Session.h"
+
+//#define MY_DEFPORT 5001
+//#define DEFAULT_MULTICASTGROUP "234.5.6.7"
+
+ACE_RCSID(Sender_QoS_Event_Handler, Sender_QoS_Event_Handler, "$Id$")
+
+class Sender_QoS_Event_Handler : public ACE_Event_Handler
+{
+public:
+ // = Initialization and Termination methods.
+ Sender_QoS_Event_Handler (void);
+ // Constructor.
+
+ Sender_QoS_Event_Handler::Sender_QoS_Event_Handler (const ACE_SOCK_Dgram_Mcast_QoS
+ &dgram_mcast_qos,
+ ACE_QoS_Session *qos_session
+ );
+ // Constructor.
+
+ ~Sender_QoS_Event_Handler (void);
+ // Destructor.
+
+ virtual ACE_HANDLE get_handle (void) const;
+ // Override this to return the handle of the Dgram_Mcast
+ // that we are using.
+
+ virtual int handle_qos (ACE_HANDLE fd);
+ // Handles a QoS event. Right now, just
+ // prints a message.
+
+private:
+
+ ACE_SOCK_Dgram_Mcast_QoS dgram_mcast_qos_;
+ ACE_QoS_Session *qos_session_;
+};
+
+#endif /* SENDER_QOS_EVENT_HANDLER_H */
diff --git a/ACE/examples/QOS/Simple/receiver.cpp b/ACE/examples/QOS/Simple/receiver.cpp
new file mode 100644
index 00000000000..72381d64f69
--- /dev/null
+++ b/ACE/examples/QOS/Simple/receiver.cpp
@@ -0,0 +1,301 @@
+/* -*- C++ -*- */
+// $Id$
+
+// ============================================================================
+//
+// = LIBRARY
+// ACE_wrappers/examples/QOS
+//
+// = FILENAME
+// server.cpp
+//
+// = AUTHOR
+// Vishal Kachroo <vishal@cs.wustl.edu>
+//
+// ============================================================================
+
+#define QOSEVENT_MAIN
+
+#include "ace/QoS/QoS_Session.h"
+#include "ace/QoS/QoS_Session_Factory.h"
+#include "ace/QoS/QoS_Decorator.h"
+#include "ace/QoS/SOCK_Dgram_Mcast_QoS.h"
+
+#include "QoS_Util.h"
+#include "Fill_ACE_QoS.h"
+#include "QoS_Signal_Handler.h"
+#include "Receiver_QoS_Event_Handler.h"
+
+// To open QOS sockets administrative access is required on the
+// machine. Fill in default values for QoS structure. The default
+// values were simply choosen from existing QOS templates available
+// via WSAGetQosByName. Notice that ProviderSpecific settings are
+// being allowed when picking the "default" template but not for
+// "well-known" QOS templates. Also notice that since data is only
+// flowing from sender to receiver, different flowspecs are filled in
+// depending upon whether this application is acting as a sender or
+// receiver.
+
+
+// This function fills up the ACE_QoS_Params with the supplied iovec
+// and ACE_QoS.
+
+int
+FillQoSParams (ACE_QoS_Params &qos_params,
+ iovec* iov,
+ ACE_QoS* qos)
+{
+ qos_params.callee_data (iov);
+ qos_params.caller_data (0);
+ qos_params.socket_qos (qos);
+ qos_params.group_socket_qos (0);
+ qos_params.flags (ACE_JL_BOTH);
+
+ return 0;
+}
+
+int
+ACE_TMAIN (int argc, ACE_TCHAR * argv[])
+{
+
+ QoS_Util qos_util(argc, argv);
+
+ if (qos_util.parse_args () == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Error in parsing args\n"),
+ -1);
+
+ // This is a multicast application.
+ if (qos_util.multicast_flag ())
+ {
+ Fill_ACE_QoS fill_ace_qos;
+
+ // The application adds the flow specs that it wants into the
+ // Fill_ACE_QoS. The Fill_ACE_QoS indexes the flow specs by the
+ // flow spec names. Here the new flowspec being added is g_711.
+ ACE_CString g_711 ("g_711");
+
+ switch (fill_ace_qos.map ().bind (g_711,
+ new ACE_Flow_Spec (9200,
+ 708,
+ 18400,
+ 0,
+ 0,
+ ACE_SERVICETYPE_CONTROLLEDLOAD,
+ 368,
+ 368,
+ 25,
+ 1)))
+ {
+ case 1 :
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Unable to bind the new flow spec\n"
+ "The Flow Spec name already exists\n"),
+ -1);
+ break;
+ case -1 :
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Unable to bind the new flow spec\n"),
+ -1);
+ break;
+ }
+
+ ACE_DEBUG ((LM_DEBUG,
+ "g_711 Flow Spec bound successfully\n"));
+
+ // This is a receiver. So we fill in the receiving QoS parameters.
+ ACE_QoS ace_qos_receiver;
+ if (fill_ace_qos.fill_simplex_receiver_qos (ace_qos_receiver,
+ g_711) !=0)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Unable to fill simplex receiver qos\n"),
+ -1);
+ else
+ ACE_DEBUG ((LM_DEBUG,
+ "Filled up the Receiver QoS parameters\n"));
+
+ // Opening a new Multicast Datagram.
+ ACE_SOCK_Dgram_Mcast_QoS dgram_mcast_qos;
+
+ // Multicast Session Address specified by user at command line.
+ // If this address is not specified,
+ // <localhost:ACE_DEFAULT_MULTICAST_PORT> is assumed.
+ ACE_INET_Addr mult_addr (*(qos_util.mult_session_addr ()));
+
+ // Fill the ACE_QoS_Params to be passed to the <ACE_OS::join_leaf>
+ // through subscribe.
+
+ ACE_QoS_Params qos_params;
+ FillQoSParams (qos_params, 0, &ace_qos_receiver);
+
+ // Create a QoS Session Factory.
+ ACE_QoS_Session_Factory session_factory;
+
+ // Ask the factory to create a QoS session. This could be RAPI or
+ // GQoS based on the parameter passed.
+ ACE_QoS_Session *qos_session =
+ session_factory.create_session ();
+
+ // Create a destination address for the QoS session. The same
+ // address should be used for the subscribe call later. A copy
+ // is made below only to distinguish the two usages of the dest
+ // address.
+
+ ACE_INET_Addr dest_addr (mult_addr);
+
+ // A QoS session is defined by the 3-tuple [DestAddr, DestPort,
+ // Protocol]. Initialize the QoS session.
+ if (qos_session->open (mult_addr,
+ IPPROTO_UDP) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Error in opening the QoS session\n"),
+ -1);
+ else
+ ACE_DEBUG ((LM_DEBUG,
+ "QoS session opened successfully\n"));
+
+ // The following call opens the Dgram_Mcast and calls the
+ // <ACE_OS::join_leaf> with the qos_params supplied here. Note
+ // the QoS session object is passed into this call. This
+ // subscribes the underlying socket to the passed in QoS
+ // session. For joining multiple multicast sessions, the
+ // following subscribe call should be made with different
+ // multicast addresses and a new QoS session object should be
+ // passed in for each such call. The QoS session objects can be
+ // created only through the session factory. Care should be
+ // taken that the mult_addr for the subscribe() call matches the
+ // dest_addr of the QoS session object. If this is not done, the
+ // subscribe call will fail. A more abstract version of
+ // subscribe will be added that constrains the various features
+ // of GQoS like different flags etc.
+
+ if (dgram_mcast_qos.subscribe (mult_addr,
+ qos_params,
+ 1,
+ 0,
+ AF_INET,
+ // ACE_FROM_PROTOCOL_INFO,
+ 0,
+ 0, // ACE_Protocol_Info,
+ 0,
+ ACE_OVERLAPPED_SOCKET_FLAG
+ | ACE_FLAG_MULTIPOINT_C_LEAF
+ | ACE_FLAG_MULTIPOINT_D_LEAF,
+ qos_session) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Error in subscribe\n"),
+ -1);
+ else
+ ACE_DEBUG ((LM_DEBUG,
+ "Dgram_Mcast subscribe succeeds \n"));
+
+ int nIP_TTL = 25;
+ char achInBuf [BUFSIZ];
+ u_long dwBytes;
+
+ // Should this be abstracted into QoS objects ?? Doesnt seem to have
+ // to do anything directly with QoS.
+ if (ACE_OS::ioctl (dgram_mcast_qos.get_handle (), // Socket.
+ ACE_SIO_MULTICAST_SCOPE, // IO control code.
+ &nIP_TTL, // In buffer.
+ sizeof (nIP_TTL), // Length of in buffer.
+ achInBuf, // Out buffer.
+ BUFSIZ, // Length of Out buffer.
+ &dwBytes, // bytes returned.
+ 0, // Overlapped.
+ 0) == -1) // Func.
+ ACE_ERROR ((LM_ERROR,
+ "Error in Multicast scope ACE_OS::ioctl() \n"));
+ else
+ ACE_DEBUG ((LM_DEBUG,
+ "Setting TTL with Multicast scope ACE_OS::ioctl call succeeds \n"));
+
+ int bFlag = 0;
+
+ // Should this be abstracted into QoS objects ?? Doesnt seem to have
+ // to do anything directly with QoS.
+ if (ACE_OS::ioctl (dgram_mcast_qos.get_handle (), // Socket.
+ ACE_SIO_MULTIPOINT_LOOPBACK, // IO control code.
+ &bFlag, // In buffer.
+ sizeof (bFlag), // Length of in buffer.
+ achInBuf, // Out buffer.
+ BUFSIZ, // Length of Out buffer.
+ &dwBytes, // bytes returned.
+ 0, // Overlapped.
+ 0) == -1) // Func.
+ ACE_ERROR ((LM_ERROR,
+ "Error in Loopback ACE_OS::ioctl() \n"));
+ else
+ ACE_DEBUG ((LM_DEBUG,
+ "Disable Loopback with ACE_OS::ioctl call succeeds \n"));
+
+ // This is a receiver.
+ qos_session->flags (ACE_QoS_Session::ACE_QOS_RECEIVER);
+
+ ACE_QoS_Manager qos_manager = dgram_mcast_qos.qos_manager ();
+
+ // Set the QoS for the session. Replaces the ioctl () call that
+ // was being made previously.
+ if (qos_session->qos (&dgram_mcast_qos,
+ &qos_manager,
+ ace_qos_receiver) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Unable to set QoS\n"),
+ -1);
+ else
+ ACE_DEBUG ((LM_DEBUG,
+ "Setting QOS succeeds.\n"));
+
+ // Register a signal handler that helps to gracefully close the
+ // open QoS sessions.
+ QoS_Signal_Handler qos_signal_handler (qos_session);
+
+ // Register the usual SIGINT signal handler with the Reactor for
+ // the application to gracefully release the QoS session and
+ // shutdown.
+ if (ACE_Reactor::instance ()->register_handler
+ (SIGINT, &qos_signal_handler) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Error in registering the Signal Handler.\n"),
+ -1);
+
+ // Handler to process QoS and Data events for the reciever.
+ Receiver_QoS_Event_Handler qos_event_handler (dgram_mcast_qos,
+ qos_session);
+
+ // Decorate the above handler with QoS functionality.
+ ACE_QoS_Decorator qos_decorator (&qos_event_handler,
+ qos_session);
+
+ // Initialize the Decorator.
+ if (qos_decorator.init () != 0)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "QoS Decorator init () failed.\n"),
+ -1);
+
+ // Register the decorated Event Handler with the Reactor.
+ if (ACE_Reactor::instance ()->register_handler (&qos_decorator,
+ ACE_Event_Handler::QOS_MASK |
+ ACE_Event_Handler::READ_MASK) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Error in registering the Decorator with the Reactor\n"),
+ -1);
+
+
+ // Start the event loop.
+ ACE_DEBUG ((LM_DEBUG,
+ "Running the Event Loop ... \n"));
+
+ ACE_Reactor::instance ()->run_event_loop ();
+
+ ACE_DEBUG ((LM_DEBUG,
+ "(%P|%t) shutting down server logging daemon\n"));
+ }
+ else
+ ACE_DEBUG ((LM_DEBUG,
+ "Specify a -m option for multicast application\n"));
+ return 0;
+}
+
+
+
diff --git a/ACE/examples/QOS/Simple/sender.cpp b/ACE/examples/QOS/Simple/sender.cpp
new file mode 100644
index 00000000000..97e6aafa407
--- /dev/null
+++ b/ACE/examples/QOS/Simple/sender.cpp
@@ -0,0 +1,315 @@
+/* -*- C++ -*- */
+// $Id$
+
+// ============================================================================
+//
+// = LIBRARY
+// ACE_wrappers/examples/QOS
+//
+// = FILENAME
+// client.cpp
+//
+// = AUTHOR
+// Vishal Kachroo <vishal@cs.wustl.edu>
+//
+// ============================================================================
+
+
+#include "ace/QoS/QoS_Session.h"
+#include "ace/QoS/QoS_Session_Factory.h"
+#include "ace/QoS/QoS_Session_Impl.h"
+#include "ace/QoS/QoS_Decorator.h"
+#include "ace/QoS/SOCK_Dgram_Mcast_QoS.h"
+
+#include "QoS_Util.h"
+#include "Fill_ACE_QoS.h"
+#include "QoS_Signal_Handler.h"
+#include "Sender_QoS_Event_Handler.h"
+
+// To open QOS sockets administrative access is required on the
+// machine. Fill in default values for QoS structure. The default
+// values were simply choosen from existing QOS templates available
+// via WSAGetQosByName. Notice that ProviderSpecific settings are
+// being allowed when picking the "default" template but not for
+// "well-known" QOS templates. Also notice that since data is only
+// flowing from sender to receiver, different flowspecs are filled in
+// depending upon whether this application is acting as a sender or
+// receiver.
+
+// This function fills up the ACE_QoS_Params with the supplied iovec and ACE_QoS.
+
+int
+FillQoSParams (ACE_QoS_Params &qos_params,
+ iovec* iov,
+ ACE_QoS* qos)
+{
+ qos_params.callee_data (iov);
+ qos_params.caller_data (0);
+ qos_params.socket_qos (qos);
+ qos_params.group_socket_qos (0);
+ qos_params.flags (ACE_JL_BOTH);
+
+ return 0;
+}
+
+int
+ACE_TMAIN (int argc, ACE_TCHAR * argv[])
+{
+
+ ACE_DEBUG ((LM_DEBUG,
+ "Sender\n"));
+
+ QoS_Util qos_util(argc, argv);
+
+ if (qos_util.parse_args () == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Error in parsing args\n"),
+ -1);
+
+ // This is a multicast application.
+ if (qos_util.multicast_flag ())
+ {
+ Fill_ACE_QoS fill_ace_qos;
+
+ // The application adds the flow specs that it wants into the
+ // Fill_ACE_QoS. The Fill_ACE_QoS indexes the flow specs by the flow
+ // spec names. Here the new flowspec being added is g_711.
+ ACE_CString g_711 ("g_711");
+
+ switch (fill_ace_qos.map ().bind (g_711,
+ new ACE_Flow_Spec (9200,
+ 708,
+ 18400,
+ 0,
+ 0,
+ ACE_SERVICETYPE_CONTROLLEDLOAD,
+ 368,
+ 368,
+ 25,
+ 1)))
+ {
+ case 1 :
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Unable to bind the new flow spec\n"
+ "The Flow Spec name already exists\n"),
+ -1);
+ break;
+ case -1 :
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Unable to bind the new flow spec\n"),
+ -1);
+ break;
+ }
+
+ ACE_DEBUG ((LM_DEBUG,
+ "g_711 Flow Spec bound successfully\n"));
+
+ // This is a sender. So we fill in the sending QoS parameters.
+ ACE_QoS ace_qos_sender;
+
+ if (fill_ace_qos.fill_simplex_sender_qos (ace_qos_sender,
+ g_711) !=0)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Unable to fill simplex sender qos\n"),
+ -1);
+ else
+ ACE_DEBUG ((LM_DEBUG,
+ "Filled up the Sender QoS parameters\n"));
+
+ // Opening a new Multicast Datagram. It is absolutely necessary that
+ // the sender and the receiver subscribe to the same multicast
+ // addresses to make sure the "multicast sessions" for the two are
+ // the same. This is used to match the RESV<->PATH states.
+ ACE_SOCK_Dgram_Mcast_QoS dgram_mcast_qos;
+
+ // Multicast Session Address specified by user at command line.
+ // If this address is not specified,
+ // <localhost:ACE_DEFAULT_MULTICAST_PORT> is assumed.
+ ACE_INET_Addr mult_addr (*(qos_util.mult_session_addr ()));
+
+ // Fill the ACE_QoS_Params to be passed to the <ACE_OS::join_leaf>
+ // through subscribe.
+
+ ACE_QoS_Params qos_params;
+ FillQoSParams (qos_params, 0, &ace_qos_sender);
+
+ // Create a QoS Session Factory.
+ ACE_QoS_Session_Factory session_factory;
+
+ // Ask the factory to create a QoS session.
+ ACE_QoS_Session *qos_session =
+ session_factory.create_session ();
+
+ // Create a destination address for the QoS session. The same
+ // address should be used for the subscribe call later. A copy is
+ // made below only to distinguish the two usages of the dest
+ // address.
+
+ ACE_INET_Addr dest_addr (mult_addr);
+
+ // A QoS session is defined by the 3-tuple [DestAddr, DestPort,
+ // Protocol]. Initialize the QoS session.
+ if (qos_session->open (mult_addr,
+ IPPROTO_UDP) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Error in opening the QoS session\n"),
+ -1);
+ else
+ ACE_DEBUG ((LM_DEBUG,
+ "QoS session opened successfully\n"));
+
+ // The following call opens the Dgram_Mcast and calls the
+ // <ACE_OS::join_leaf> with the qos_params supplied here. Note the
+ // QoS session object is passed into this call. This subscribes the
+ // underlying socket to the passed in QoS session. For joining
+ // multiple multicast sessions, the following subscribe call should
+ // be made with different multicast addresses and a new QoS session
+ // object should be passed in for each such call. The QoS session
+ // objects can be created only through the session factory. Care
+ // should be taken that the mult_addr for the subscribe() call
+ // matches the dest_addr of the QoS session object. If this is not
+ // done, the subscribe call will fail. A more abstract version of
+ // subscribe will be added that constrains the various features of
+ // GQoS like different flags etc.
+
+ if (dgram_mcast_qos.subscribe (mult_addr,
+ qos_params,
+ 1,
+ 0,
+ AF_INET,
+ // ACE_FROM_PROTOCOL_INFO,
+ 0,
+ 0, // ACE_Protocol_Info,
+ 0,
+ ACE_OVERLAPPED_SOCKET_FLAG
+ | ACE_FLAG_MULTIPOINT_C_LEAF
+ | ACE_FLAG_MULTIPOINT_D_LEAF,
+ qos_session) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Error in subscribe\n"),
+ -1);
+ else
+ ACE_DEBUG ((LM_DEBUG,
+ "Dgram_Mcast subscribe succeeds \n"));
+
+ int nIP_TTL = 25;
+ char achInBuf [BUFSIZ];
+ u_long dwBytes;
+
+ // Should this be abstracted into QoS objects ?? Doesnt seem to have
+ // to do anything directly with QoS.
+ if (ACE_OS::ioctl (dgram_mcast_qos.get_handle (), // Socket.
+ ACE_SIO_MULTICAST_SCOPE, // IO control code.
+ &nIP_TTL, // In buffer.
+ sizeof (nIP_TTL), // Length of in buffer.
+ achInBuf, // Out buffer.
+ BUFSIZ, // Length of Out buffer.
+ &dwBytes, // bytes returned.
+ 0, // Overlapped.
+ 0) == -1) // Func.
+ ACE_ERROR ((LM_ERROR,
+ "Error in Multicast scope ACE_OS::ioctl() \n"));
+ else
+ ACE_DEBUG ((LM_DEBUG,
+ "Setting TTL with Multicast scope ACE_OS::ioctl call succeeds \n"));
+
+ int bFlag = 0;
+
+ // Should this be abstracted into QoS objects ?? Doesnt seem to have
+ // to do anything directly with QoS.
+ if (ACE_OS::ioctl (dgram_mcast_qos.get_handle (), // Socket.
+ ACE_SIO_MULTIPOINT_LOOPBACK, // IO control code.
+ &bFlag, // In buffer.
+ sizeof (bFlag), // Length of in buffer.
+ achInBuf, // Out buffer.
+ BUFSIZ, // Length of Out buffer.
+ &dwBytes, // bytes returned.
+ 0, // Overlapped.
+ 0) == -1) // Func.
+ ACE_ERROR ((LM_ERROR,
+ "Error in Loopback ACE_OS::ioctl() \n"));
+ else
+ ACE_DEBUG ((LM_DEBUG,
+ "Disable Loopback with ACE_OS::ioctl call succeeds \n"));
+
+ // This is a sender.
+ qos_session->flags (ACE_QoS_Session::ACE_QOS_SENDER);
+
+ ACE_QoS_Manager qos_manager = dgram_mcast_qos.qos_manager ();
+
+ // Since we are using RSVP, it is imperative that the client
+ // application have the option of supplying the source sender
+ // port for the RSVP messages. A default will be chosen by the
+ // ACE API if this is not done.
+ qos_session->source_port (qos_util.source_port ());
+
+ // Set the QoS for the session. Replaces the ioctl () call that
+ // was being made previously.
+ if (qos_session->qos (&dgram_mcast_qos,
+ &qos_manager,
+ ace_qos_sender) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Unable to set QoS\n"),
+ -1);
+ else
+ ACE_DEBUG ((LM_DEBUG,
+ "Setting QOS succeeds.\n"));
+
+ // Register a signal handler that helps to gracefully close the open
+ // QoS sessions.
+ QoS_Signal_Handler qos_signal_handler (qos_session);
+
+ // Register the usual SIGINT signal handler with the Reactor for
+ // the application to gracefully release the QoS session and
+ // shutdown.
+ if (ACE_Reactor::instance ()->register_handler
+ (SIGINT, &qos_signal_handler) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Error in registering the Signal Handler.\n"),
+ -1);
+
+ // Handler to process QoS and Data events for the reciever.
+ Sender_QoS_Event_Handler qos_event_handler (dgram_mcast_qos,
+ qos_session);
+
+ // Decorate the above handler with QoS functionality.
+ ACE_QoS_Decorator qos_decorator (&qos_event_handler,
+ qos_session);
+
+ // Initialize the Decorator.
+ if (qos_decorator.init () != 0)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "QoS Decorator init () failed.\n"),
+ -1);
+
+ // Register the decorated Event Handler with the Reactor.
+ if (ACE_Reactor::instance ()->register_handler (&qos_decorator,
+ ACE_Event_Handler::QOS_MASK |
+ ACE_Event_Handler::READ_MASK) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Error in registering the Decorator with the Reactor\n"),
+ -1);
+
+
+
+ // Start the event loop.
+ ACE_DEBUG ((LM_DEBUG,
+ "Running the Event Loop ... \n"));
+
+ ACE_Reactor::instance ()->run_event_loop ();
+
+ ACE_DEBUG ((LM_DEBUG,
+ "(%P|%t) shutting down server logging daemon\n"));
+ }
+ else
+ ACE_DEBUG ((LM_DEBUG,
+ "Specify a -m option for multicast application\n"));
+ return 0;
+}
+
+
+
+
+
+
+
diff --git a/ACE/examples/README b/ACE/examples/README
new file mode 100644
index 00000000000..4f2629dfba9
--- /dev/null
+++ b/ACE/examples/README
@@ -0,0 +1,77 @@
+This directory contains a number of examples that illustrate how to
+use the following ACE library components. If you want to see how
+to program using ACE, this is the best place to start reading code and
+learning the ACE design.
+
+These examples are roughly divided up according to the class
+categories in ACE. For more information on ACE class categories,
+please take a look at $ACE_ROOT/ACE-categories.
+
+ . ASX
+ Illustrate various components in the ADAPTIVE Service
+ eXecutive, which is a user-level implementation of
+ System V STREAMS written in C++.
+
+ . Connection
+ Illustrate how the various Acceptor and Connector
+ components can be used.
+
+ . IOStream
+ Illustrate how the ACE IOStreams wrapper works.
+
+ . IPC_SAP
+ Illustrate the C++ wrappers for Sockets, TLI, UNIX and
+ Win32 Named Pipes, and UNIX Stream Pipes.
+
+ . Log_Msg
+ Illustrate some of the features of the logging
+ facility used in ACE to consolidate debugging and
+ error report.
+
+ . Logger
+ This is a simple version of a Server Logging Daemon
+ that illustrates the "bare-bones" usage of the
+ Reactor. A more sophisticated set of logging examples
+ are in the $ACE_ROOT/netsvcs/{client,lib,server}
+ directories.
+
+ . Mem_Map
+ Illustrate how the ACE memory-mapped file components
+ work.
+
+ . Misc
+ Various miscellaneous tests that illustrate how ACE
+ utility components work.
+
+ . NT_Service
+ Illustrates how to write an NT Service using the
+ ACE_NT_Service class, and how to insert it and remove it
+ in the SCM, start it, and stop it, and how to run as a
+ service.
+
+ . Reactor
+ Contains many examples of how to utilize the ACE
+ object-oriented event demultiplexer.
+
+ . Service_Configurator
+ Illustrates the use of the ACE mechanism for
+ dynamically configuring communication services.
+
+ . Shared_Malloc
+ Illustrates the use of ACE wrappers for
+ sophisticated use of the ACE_Malloc shared
+ memory components.
+
+ . Shared_Memory
+ Illustrates the use of simple ACE wrappers for
+ shared memory and memory mapped file.
+
+ . System_V_IPC
+ Illustrates how to use the ACE wrappers for System V
+ IPC (i.e., semphores, shared memory, and message
+ queues).
+
+ . Threads
+ Illustrates the use of ACE wrappers for threading
+ and synchronization.
+
diff --git a/ACE/examples/Reactor/Dgram/.cvsignore b/ACE/examples/Reactor/Dgram/.cvsignore
new file mode 100644
index 00000000000..94126b14c4e
--- /dev/null
+++ b/ACE/examples/Reactor/Dgram/.cvsignore
@@ -0,0 +1,4 @@
+codgram
+codgram
+dgram
+dgram
diff --git a/ACE/examples/Reactor/Dgram/CODgram.cpp b/ACE/examples/Reactor/Dgram/CODgram.cpp
new file mode 100644
index 00000000000..f423c43fb8c
--- /dev/null
+++ b/ACE/examples/Reactor/Dgram/CODgram.cpp
@@ -0,0 +1,254 @@
+// $Id$
+
+// Exercise the <ACE_SOCK_CODgram> wrapper along with the
+// <ACE_Reactor>. This test simply ping-pongs datagrams back and
+// forth between the peer1 and peer2 processes. This test can
+// be run in two ways:
+//
+// 1. Stand-alone -- e.g.,
+//
+// % ./CODgram
+//
+// which will spawn a child process and run peer1 and peer2
+// in different processes on the same machine.
+//
+// 2. Distributed -- e.g.,
+//
+// # Peer1
+// % ./CODgram 10002 tango.cs.wustl.edu 10003 peer1
+//
+// # Peer1
+// % ./CODgram 10003 tango.cs.wustl.edu 10002 peer2
+//
+// which will run peer1 and peer2 in different processes
+// on the same or different machines. Note that you MUST
+// give the name "peer1" as the final argument to one and
+// only one of the programs so that the test will work properly.
+
+#include "ace/OS_main.h"
+#include "ace/OS_NS_string.h"
+#include "ace/OS_NS_unistd.h"
+#include "ace/Reactor.h"
+#include "ace/SOCK_CODgram.h"
+#include "ace/INET_Addr.h"
+#include "ace/Process.h"
+#include "ace/Log_Msg.h"
+
+ACE_RCSID(Dgram, CODgram, "$Id$")
+
+// Port used to receive for dgrams.
+static u_short port1;
+
+class Dgram_Endpoint : public ACE_Event_Handler
+{
+public:
+ Dgram_Endpoint (const ACE_INET_Addr &remote_addr,
+ const ACE_INET_Addr &local_addr);
+
+ // = Hook methods inherited from the <ACE_Event_Handler>.
+ virtual ACE_HANDLE get_handle (void) const;
+ virtual int handle_input (ACE_HANDLE handle);
+ virtual int handle_timeout (const ACE_Time_Value & tv,
+ const void *arg = 0);
+
+ virtual int handle_close (ACE_HANDLE handle,
+ ACE_Reactor_Mask close_mask);
+
+ int send (const char *buf, size_t len);
+ // Send the <buf> to the peer.
+
+private:
+ ACE_SOCK_CODgram endpoint_;
+ // Wrapper for sending/receiving dgrams.
+};
+
+int
+Dgram_Endpoint::send (const char *buf, size_t len)
+{
+ return this->endpoint_.send (buf, len);
+}
+
+int
+Dgram_Endpoint::handle_close (ACE_HANDLE handle,
+ ACE_Reactor_Mask)
+{
+ ACE_UNUSED_ARG (handle);
+
+ this->endpoint_.close ();
+ return 0;
+}
+
+Dgram_Endpoint::Dgram_Endpoint (const ACE_INET_Addr &remote_addr,
+ const ACE_INET_Addr &local_addr)
+ : endpoint_ (remote_addr, local_addr)
+{
+}
+
+ACE_HANDLE
+Dgram_Endpoint::get_handle (void) const
+{
+ return this->endpoint_.get_handle ();
+}
+
+int
+Dgram_Endpoint::handle_input (ACE_HANDLE)
+{
+ char buf[BUFSIZ];
+
+ ACE_DEBUG ((LM_DEBUG,
+ "(%P|%t) activity occurred on handle %d!\n",
+ this->endpoint_.get_handle ()));
+
+ ssize_t n = this->endpoint_.recv (buf, sizeof buf);
+
+ if (n == -1)
+ ACE_ERROR ((LM_ERROR,
+ "%p\n",
+ "handle_input"));
+ else
+ ACE_DEBUG ((LM_DEBUG,
+ "(%P|%t) buf of size %d = %*s\n",
+ n, n, buf));
+ return 0;
+}
+
+int
+Dgram_Endpoint::handle_timeout (const ACE_Time_Value &,
+ const void *)
+{
+ ACE_DEBUG ((LM_DEBUG,
+ "(%P|%t) timed out for endpoint\n"));
+ return 0;
+}
+
+static int
+run_test (u_short localport,
+ const ACE_TCHAR *remotehost,
+ u_short remoteport,
+ const ACE_TCHAR *peer)
+{
+ ACE_INET_Addr remote_addr (remoteport,
+ remotehost);
+ ACE_INET_Addr local_addr (localport);
+
+ Dgram_Endpoint endpoint (remote_addr, local_addr);
+
+ // Read data from other side.
+ if (ACE_Reactor::instance ()->register_handler
+ (&endpoint,
+ ACE_Event_Handler::READ_MASK) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "ACE_Reactor::register_handler"),
+ -1);
+ char buf[BUFSIZ];
+ ACE_OS::strcpy (buf,
+ "Data to transmit");
+ size_t len = ACE_OS::strlen (buf);
+
+ // "peer1" is the "initiator."
+ if (ACE_OS::strncmp (peer, ACE_TEXT("peer1"), 5) == 0)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ "(%P|%t) sending data\n"));
+ for (size_t i = 0; i < 20; i++)
+ {
+ endpoint.send (buf, len);
+ ACE_DEBUG ((LM_DEBUG,
+ "(%P|%t) .\n"));
+ ACE_OS::sleep (1);
+ }
+ }
+
+ for (int i = 0; i < 40; i++)
+ {
+ // Wait up to 10 seconds for data.
+ ACE_Time_Value tv (10, 0);
+
+ if (ACE_Reactor::instance ()->handle_events (tv) <= 0)
+ ACE_ERROR_RETURN ((LM_DEBUG,
+ "(%P|%t) %p\n",
+ "handle_events"),
+ -1);
+ ACE_DEBUG ((LM_DEBUG,
+ "(%P|%t) return from handle events\n"));
+
+ endpoint.send (buf, len);
+
+ ACE_DEBUG ((LM_DEBUG,
+ "(%P|%t) .\n"));
+ }
+
+ if (ACE_Reactor::instance ()->remove_handler
+ (&endpoint,
+ ACE_Event_Handler::READ_MASK) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "ACE_Reactor::remove_handler"),
+ -1);
+ ACE_DEBUG ((LM_DEBUG,
+ "(%P|%t) exiting\n"));
+ return 0;
+}
+
+int
+ACE_TMAIN (int argc, ACE_TCHAR *argv[])
+{
+ // Estabish call backs and socket names.
+
+ port1 = argc > 1 ? ACE_OS::atoi (argv[1]) : ACE_DEFAULT_SERVER_PORT;
+ const ACE_TCHAR *remotehost = argc > 2 ? argv[2] : ACE_DEFAULT_SERVER_HOST;
+ const u_short port2 = argc > 3 ? ACE_OS::atoi (argv[3]) : port1 + 1;
+
+ // Providing the fourth command line argument indicates we don't
+ // want to spawn a new process. On Win32, we use this to exec the
+ // new program.
+ if (argc > 4)
+ run_test (port1,
+ remotehost,
+ port2,
+ argv[4]);
+ else
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ "(%P|%t) local port = %d, remote host = %s, remote port = %d\n",
+ port1,
+ remotehost,
+ port2));
+
+ ACE_Process_Options options;
+ options.command_line ("%s %d %s %d %c",
+ argv[0],
+ port1,
+ remotehost,
+ port2,
+ 'c');
+
+ // This has no effect on NT and will spawn a process that exec
+ // the above run_test function.
+ options.creation_flags (ACE_Process_Options::NO_EXEC);
+
+ ACE_Process new_process;
+
+ switch (new_process.spawn (options))
+ {
+ case -1:
+ return -1;
+
+ case 0:
+ run_test (port1,
+ remotehost,
+ port2,
+ ACE_TEXT("peer1"));
+ break;
+
+ default:
+ run_test (port2,
+ remotehost,
+ port1,
+ ACE_TEXT("peer2"));
+ new_process.wait ();
+ break;
+ }
+ }
+
+ return 0;
+}
diff --git a/ACE/examples/Reactor/Dgram/Dgram.cpp b/ACE/examples/Reactor/Dgram/Dgram.cpp
new file mode 100644
index 00000000000..c4c21e84186
--- /dev/null
+++ b/ACE/examples/Reactor/Dgram/Dgram.cpp
@@ -0,0 +1,258 @@
+// $Id$
+
+// Exercise the <ACE_SOCK_Dgram> wrapper along with the <ACE_Reactor>.
+// This test simply ping-pongs datagrams back and forth between the
+// peer1 and peer2 processes. This test can be run in two ways:
+//
+// 1. Stand-alone -- e.g.,
+//
+// % ./Dgram
+//
+// which will spawn a child process and run peer1 and peer2
+// in different processes on the same machine.
+//
+// 2. Distributed -- e.g.,
+//
+// # Peer1
+// % ./Dgram 10002 tango.cs.wustl.edu 10003 peer1
+//
+// # Peer1
+// % ./Dgram 10003 tango.cs.wustl.edu 10002 peer2
+//
+// which will run peer1 and peer2 in different processes
+// on the same or different machines. Note that you MUST
+// give the name "peer1" as the final argument to one and
+// only one of the programs so that the test will work properly.
+
+#include "ace/OS_main.h"
+#include "ace/OS_NS_string.h"
+#include "ace/OS_NS_unistd.h"
+#include "ace/Reactor.h"
+#include "ace/Process.h"
+#include "ace/SOCK_Dgram.h"
+#include "ace/INET_Addr.h"
+#include "ace/Log_Msg.h"
+
+ACE_RCSID(Dgram, Dgram, "$Id$")
+
+// Port used to receive for dgrams.
+static u_short port1;
+
+class Dgram_Endpoint : public ACE_Event_Handler
+{
+public:
+ Dgram_Endpoint (const ACE_INET_Addr &local_addr);
+
+ // = Hook methods inherited from the <ACE_Event_Handler>.
+ virtual ACE_HANDLE get_handle (void) const;
+ virtual int handle_input (ACE_HANDLE handle);
+ virtual int handle_timeout (const ACE_Time_Value & tv,
+ const void *arg = 0);
+ virtual int handle_close (ACE_HANDLE handle,
+ ACE_Reactor_Mask close_mask);
+
+ int send (const char *buf, size_t len, const ACE_INET_Addr &);
+ // Send the <buf> to the peer.
+
+private:
+ ACE_SOCK_Dgram endpoint_;
+ // Wrapper for sending/receiving dgrams.
+};
+
+int
+Dgram_Endpoint::send (const char *buf,
+ size_t len,
+ const ACE_INET_Addr &addr)
+{
+ return this->endpoint_.send (buf, len, addr);
+}
+
+Dgram_Endpoint::Dgram_Endpoint (const ACE_INET_Addr &local_addr)
+ : endpoint_ (local_addr)
+{
+}
+
+ACE_HANDLE
+Dgram_Endpoint::get_handle (void) const
+{
+ return this->endpoint_.get_handle ();
+}
+
+int
+Dgram_Endpoint::handle_close (ACE_HANDLE handle,
+ ACE_Reactor_Mask)
+{
+ ACE_UNUSED_ARG (handle);
+
+ this->endpoint_.close ();
+ delete this;
+ return 0;
+}
+
+int
+Dgram_Endpoint::handle_input (ACE_HANDLE)
+{
+ char buf[BUFSIZ];
+ ACE_INET_Addr from_addr;
+
+ ACE_DEBUG ((LM_DEBUG,
+ "(%P|%t) activity occurred on handle %d!\n",
+ this->endpoint_.get_handle ()));
+
+ ssize_t n = this->endpoint_.recv (buf,
+ sizeof buf,
+ from_addr);
+
+ if (n == -1)
+ ACE_ERROR ((LM_ERROR,
+ "%p\n",
+ "handle_input"));
+ else
+ ACE_DEBUG ((LM_DEBUG,
+ "(%P|%t) buf of size %d = %*s\n",
+ n,
+ n,
+ buf));
+ return 0;
+}
+
+int
+Dgram_Endpoint::handle_timeout (const ACE_Time_Value &,
+ const void *)
+{
+ ACE_DEBUG ((LM_DEBUG,
+ "(%P|%t) timed out for endpoint\n"));
+ return 0;
+}
+
+static int
+run_test (u_short localport,
+ const ACE_TCHAR *remotehost,
+ u_short remoteport,
+ const ACE_TCHAR *peer)
+{
+ ACE_INET_Addr remote_addr (remoteport,
+ remotehost);
+ ACE_INET_Addr local_addr (localport);
+
+ Dgram_Endpoint *endpoint;
+
+ ACE_NEW_RETURN (endpoint,
+ Dgram_Endpoint (local_addr),
+ -1);
+
+ // Read data from other side.
+ if (ACE_Reactor::instance ()->register_handler
+ (endpoint,
+ ACE_Event_Handler::READ_MASK) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "ACE_Reactor::register_handler"),
+ -1);
+
+ char buf[BUFSIZ];
+ ACE_OS::strcpy (buf, "Data to transmit");
+ size_t len = ACE_OS::strlen (buf);
+
+ if (ACE_OS::strncmp (peer, ACE_TEXT("peer1"), 5) == 0)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ "(%P|%t) sending data\n"));
+
+ for (size_t i = 0; i < 20; i++)
+ {
+ endpoint->send (buf, len, remote_addr);
+ ACE_DEBUG ((LM_DEBUG,
+ "(%P|%t) .\n"));
+ ACE_OS::sleep (1);
+ }
+ }
+
+ for (int i = 0; i < 40; i++)
+ {
+ // Wait up to 10 seconds for data.
+ ACE_Time_Value tv (10, 0);
+
+ if (ACE_Reactor::instance ()->handle_events (tv) <= 0)
+ ACE_ERROR_RETURN ((LM_DEBUG,
+ "(%P|%t) %p\n",
+ "handle_events"),
+ -1);
+
+ ACE_DEBUG ((LM_DEBUG,
+ "(%P|%t) return from handle events\n"));
+
+ endpoint->send (buf, len, remote_addr);
+
+ ACE_DEBUG ((LM_DEBUG,
+ "(%P|%t) .\n"));
+ }
+
+ if (ACE_Reactor::instance ()->remove_handler
+ (endpoint,
+ ACE_Event_Handler::READ_MASK) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "ACE_Reactor::remove_handler"),
+ -1);
+ ACE_DEBUG ((LM_DEBUG,
+ "(%P|%t) exiting\n"));
+ return 0;
+}
+
+int
+ACE_TMAIN (int argc, ACE_TCHAR *argv[])
+{
+ // Estabish call backs and socket names.
+
+ port1 = argc > 1 ? ACE_OS::atoi (argv[1]) : ACE_DEFAULT_SERVER_PORT;
+ const ACE_TCHAR *remotehost = argc > 2 ? argv[2] : ACE_DEFAULT_SERVER_HOST;
+ const u_short port2 = argc > 3 ? ACE_OS::atoi (argv[3]) : port1 + 1;
+
+ // Providing the fourth command line argument indicate we don't want
+ // to spawn a new process. On Win32, we use this to exec the new
+ // program.
+ if (argc > 4)
+ run_test (port1, remotehost, port2, argv[4]);
+ else
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ "(%P|%t) local port = %d, remote host = %s, remote port = %d\n",
+ port1,
+ remotehost,
+ port2));
+
+ ACE_Process_Options options;
+ options.command_line ("%s %d %s %d %c",
+ argv[0],
+ port1,
+ remotehost,
+ port2,
+ 'c');
+
+ // This has no effect on NT and will spawn a process that exec
+ // the above run_test function.
+ options.creation_flags (ACE_Process_Options::NO_EXEC);
+
+ ACE_Process new_process;
+ switch (new_process.spawn (options))
+ {
+ case -1:
+ return -1;
+
+ case 0:
+ run_test (port1,
+ remotehost,
+ port2,
+ ACE_TEXT("peer1"));
+ break;
+
+ default:
+ run_test (port2,
+ remotehost,
+ port1,
+ ACE_TEXT("peer2"));
+ new_process.wait ();
+ break;
+ }
+ }
+ return 0;
+}
diff --git a/ACE/examples/Reactor/Dgram/Makefile.am b/ACE/examples/Reactor/Dgram/Makefile.am
new file mode 100644
index 00000000000..797f4b3d75e
--- /dev/null
+++ b/ACE/examples/Reactor/Dgram/Makefile.am
@@ -0,0 +1,51 @@
+## Process this file with automake to create Makefile.in
+##
+## $Id$
+##
+## This file was generated by MPC. Any changes made directly to
+## this file will be lost the next time it is generated.
+##
+## MPC Command:
+## /acebuilds/ACE_wrappers-repository/bin/mwc.pl -include /acebuilds/MPC/config -include /acebuilds/MPC/templates -feature_file /acebuilds/ACE_wrappers-repository/local.features -noreldefs -type automake -exclude build,Kokyu
+
+ACE_BUILDDIR = $(top_builddir)
+ACE_ROOT = $(top_srcdir)
+
+
+## Makefile.Reactor_Dgram.am
+noinst_PROGRAMS = dgram
+
+dgram_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+dgram_SOURCES = \
+ Dgram.cpp
+
+dgram_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Makefile.Reactor_Dgram_CO.am
+
+if !BUILD_ACE_FOR_TAO
+noinst_PROGRAMS += codgram
+
+codgram_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+codgram_SOURCES = \
+ CODgram.cpp
+
+codgram_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+endif !BUILD_ACE_FOR_TAO
+
+## Clean up template repositories, etc.
+clean-local:
+ -rm -f *~ *.bak *.rpo *.sym lib*.*_pure_* core core.*
+ -rm -f gcctemp.c gcctemp so_locations *.ics
+ -rm -rf cxx_repository ptrepository ti_files
+ -rm -rf templateregistry ir.out
+ -rm -rf ptrepository SunWS_cache Templates.DB
diff --git a/ACE/examples/Reactor/Dgram/Reactor_Dgram.mpc b/ACE/examples/Reactor/Dgram/Reactor_Dgram.mpc
new file mode 100644
index 00000000000..1040aedc184
--- /dev/null
+++ b/ACE/examples/Reactor/Dgram/Reactor_Dgram.mpc
@@ -0,0 +1,18 @@
+// -*- MPC -*-
+// $Id$
+
+project(*CO) : aceexe {
+ avoids += ace_for_tao
+ exename = codgram
+ Source_Files {
+ CODgram.cpp
+ }
+}
+
+project : aceexe {
+ exename = dgram
+ Source_Files {
+ Dgram.cpp
+ }
+}
+
diff --git a/ACE/examples/Reactor/FIFO/.cvsignore b/ACE/examples/Reactor/FIFO/.cvsignore
new file mode 100644
index 00000000000..955ffdc75d5
--- /dev/null
+++ b/ACE/examples/Reactor/FIFO/.cvsignore
@@ -0,0 +1,4 @@
+client
+client
+server
+server
diff --git a/ACE/examples/Reactor/FIFO/Makefile.am b/ACE/examples/Reactor/FIFO/Makefile.am
new file mode 100644
index 00000000000..5540e860968
--- /dev/null
+++ b/ACE/examples/Reactor/FIFO/Makefile.am
@@ -0,0 +1,56 @@
+## Process this file with automake to create Makefile.in
+##
+## $Id$
+##
+## This file was generated by MPC. Any changes made directly to
+## this file will be lost the next time it is generated.
+##
+## MPC Command:
+## /acebuilds/ACE_wrappers-repository/bin/mwc.pl -include /acebuilds/MPC/config -include /acebuilds/MPC/templates -feature_file /acebuilds/ACE_wrappers-repository/local.features -noreldefs -type automake -exclude build,Kokyu
+
+ACE_BUILDDIR = $(top_builddir)
+ACE_ROOT = $(top_srcdir)
+
+noinst_PROGRAMS =
+
+## Makefile.Reactor_FIFO_Client.am
+
+if !BUILD_ACE_FOR_TAO
+noinst_PROGRAMS += client
+
+client_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+client_SOURCES = \
+ client.cpp
+
+client_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+endif !BUILD_ACE_FOR_TAO
+
+## Makefile.Reactor_FIFO_Server.am
+
+if !BUILD_ACE_FOR_TAO
+noinst_PROGRAMS += server
+
+server_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+server_SOURCES = \
+ server.cpp
+
+server_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+endif !BUILD_ACE_FOR_TAO
+
+## Clean up template repositories, etc.
+clean-local:
+ -rm -f *~ *.bak *.rpo *.sym lib*.*_pure_* core core.*
+ -rm -f gcctemp.c gcctemp so_locations *.ics
+ -rm -rf cxx_repository ptrepository ti_files
+ -rm -rf templateregistry ir.out
+ -rm -rf ptrepository SunWS_cache Templates.DB
diff --git a/ACE/examples/Reactor/FIFO/Reactor_FIFO.mpc b/ACE/examples/Reactor/FIFO/Reactor_FIFO.mpc
new file mode 100644
index 00000000000..072ec5412b8
--- /dev/null
+++ b/ACE/examples/Reactor/FIFO/Reactor_FIFO.mpc
@@ -0,0 +1,18 @@
+// -*- MPC -*-
+// $Id$
+
+project(*client) : aceexe {
+ avoids += ace_for_tao
+ exename = client
+ Source_Files {
+ client.cpp
+ }
+}
+
+project(*server) : aceexe {
+ avoids += ace_for_tao
+ exename = server
+ Source_Files {
+ server.cpp
+ }
+}
diff --git a/ACE/examples/Reactor/FIFO/client.cpp b/ACE/examples/Reactor/FIFO/client.cpp
new file mode 100644
index 00000000000..daa8d3304ad
--- /dev/null
+++ b/ACE/examples/Reactor/FIFO/client.cpp
@@ -0,0 +1,23 @@
+// $Id$
+
+#include "ace/FIFO_Send_Msg.h"
+#include "ace/Log_Msg.h"
+#include "ace/OS_NS_stropts.h"
+
+ACE_RCSID(FIFO, client, "$Id$")
+
+int
+ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ char buf[] = "hello world";
+ ACE_Str_Buf msg (buf, sizeof buf);
+
+ ACE_FIFO_Send_Msg fifo_sender (ACE_DEFAULT_RENDEZVOUS,
+ O_WRONLY | O_CREAT,
+ ACE_DEFAULT_FILE_PERMS);
+
+ if (fifo_sender.send (msg) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "send error for fifo"), -1);
+ else
+ return 0;
+}
diff --git a/ACE/examples/Reactor/FIFO/server.cpp b/ACE/examples/Reactor/FIFO/server.cpp
new file mode 100644
index 00000000000..b6e91dd5046
--- /dev/null
+++ b/ACE/examples/Reactor/FIFO/server.cpp
@@ -0,0 +1,89 @@
+// $Id$
+
+#include "ace/Service_Config.h"
+#include "ace/Reactor.h"
+#include "ace/Event_Handler.h"
+#include "ace/FIFO_Recv_Msg.h"
+#include "ace/Log_Msg.h"
+#include "ace/OS_NS_unistd.h"
+#include "ace/OS_NS_stropts.h"
+
+ACE_RCSID(FIFO, server, "$Id$")
+
+class FIFO_Recv_Handler : public ACE_Event_Handler
+{
+public:
+ FIFO_Recv_Handler (void);
+ ~FIFO_Recv_Handler (void);
+
+ virtual ACE_HANDLE get_handle (void) const;
+ virtual int handle_input (ACE_HANDLE fd);
+
+private:
+ ACE_FIFO_Recv_Msg fifo_reader_;
+};
+
+FIFO_Recv_Handler::FIFO_Recv_Handler (void)
+{
+ ACE_OS::unlink (ACE_DEFAULT_RENDEZVOUS);
+
+ // Make sure to open the FIFO with the "persistent" flag enabled
+ // (which is the default).
+ if (this->fifo_reader_.open (ACE_DEFAULT_RENDEZVOUS) == -1)
+ ACE_ERROR ((LM_ERROR, ACE_TEXT ("%p\n"), ACE_TEXT ("open")));
+
+ // Register with the Reactor.
+ if (ACE_Reactor::instance ()->register_handler
+ (this, ACE_Event_Handler::READ_MASK) == -1)
+ ACE_ERROR ((LM_ERROR, ACE_TEXT ("%p\n"), ACE_TEXT ("register_handler")));
+}
+
+ACE_HANDLE
+FIFO_Recv_Handler::get_handle (void) const
+{
+ return this->fifo_reader_.get_handle ();
+}
+
+FIFO_Recv_Handler::~FIFO_Recv_Handler (void)
+{
+ this->fifo_reader_.close ();
+ this->fifo_reader_.remove ();
+}
+
+int
+FIFO_Recv_Handler::handle_input (ACE_HANDLE)
+{
+ char buf[BUFSIZ];
+
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("handle_input\n")));
+
+ ACE_Str_Buf msg (buf, 0, sizeof buf);
+
+ ssize_t n = this->fifo_reader_.recv (msg);
+
+ if (n < 0)
+ ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("%p\n"), ACE_TEXT ("recv")), -1);
+ else
+ {
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("msg.len = %d, n = %d\n"), msg.len, n));
+
+ if (msg.len > 0)
+ {
+ // Do some work in here...
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("msg.buf = %C\n"), msg.buf));
+ }
+ return 0;
+ }
+}
+
+int
+ACE_TMAIN (int, ACE_TCHAR *argv[])
+{
+ ACE_Service_Config daemon (argv[0]);
+
+ FIFO_Recv_Handler fr_handler;
+
+ ACE_Reactor::instance ()->run_reactor_event_loop ();
+
+ return 0;
+}
diff --git a/ACE/examples/Reactor/Makefile.am b/ACE/examples/Reactor/Makefile.am
new file mode 100644
index 00000000000..24d9217302d
--- /dev/null
+++ b/ACE/examples/Reactor/Makefile.am
@@ -0,0 +1,20 @@
+## Process this file with automake to create Makefile.in
+##
+## $Id$
+##
+## This file was generated by MPC. Any changes made directly to
+## this file will be lost the next time it is generated.
+##
+## MPC Command:
+## /acebuilds/ACE_wrappers-repository/bin/mwc.pl -include /acebuilds/MPC/config -include /acebuilds/MPC/templates -feature_file /acebuilds/ACE_wrappers-repository/local.features -noreldefs -type automake -exclude build,Kokyu
+
+SUBDIRS = \
+ Dgram \
+ FIFO \
+ Misc \
+ Multicast \
+ Ntalker \
+ Proactor \
+ TP_Reactor \
+ WFMO_Reactor
+
diff --git a/ACE/examples/Reactor/Misc/.cvsignore b/ACE/examples/Reactor/Misc/.cvsignore
new file mode 100644
index 00000000000..f7cc1865efa
--- /dev/null
+++ b/ACE/examples/Reactor/Misc/.cvsignore
@@ -0,0 +1,16 @@
+demuxing
+demuxing
+early_timeouts
+early_timeouts
+notification
+notification
+pingpong
+pingpong
+reactors
+reactors
+signals_1
+signals_1
+signals_2
+signals_2
+timer_queue
+timer_queue
diff --git a/ACE/examples/Reactor/Misc/Makefile.am b/ACE/examples/Reactor/Misc/Makefile.am
new file mode 100644
index 00000000000..47111585f87
--- /dev/null
+++ b/ACE/examples/Reactor/Misc/Makefile.am
@@ -0,0 +1,137 @@
+## Process this file with automake to create Makefile.in
+##
+## $Id$
+##
+## This file was generated by MPC. Any changes made directly to
+## this file will be lost the next time it is generated.
+##
+## MPC Command:
+## /acebuilds/ACE_wrappers-repository/bin/mwc.pl -include /acebuilds/MPC/config -include /acebuilds/MPC/templates -feature_file /acebuilds/ACE_wrappers-repository/local.features -noreldefs -type automake -exclude build,Kokyu
+
+ACE_BUILDDIR = $(top_builddir)
+ACE_ROOT = $(top_srcdir)
+
+## Makefile.Reactor_Misc_Demuxing.am
+noinst_PROGRAMS = demuxing
+
+demuxing_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+demuxing_SOURCES = \
+ test_demuxing.cpp
+
+demuxing_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Makefile.Reactor_Misc_Early_Timeouts.am
+noinst_PROGRAMS += early_timeouts
+
+early_timeouts_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+early_timeouts_SOURCES = \
+ test_early_timeouts.cpp
+
+early_timeouts_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Makefile.Reactor_Misc_Event_Handler_t.am
+noinst_PROGRAMS += event_handler_t
+
+event_handler_t_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+event_handler_t_SOURCES = \
+ test_event_handler_t.cpp
+
+event_handler_t_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Makefile.Reactor_Misc_Notification.am
+noinst_PROGRAMS += notification
+
+notification_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+notification_SOURCES = \
+ notification.cpp
+
+notification_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Makefile.Reactor_Misc_Pingpong.am
+noinst_PROGRAMS += pingpong
+
+pingpong_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+pingpong_SOURCES = \
+ pingpong.cpp
+
+pingpong_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Makefile.Reactor_Misc_Reactors.am
+noinst_PROGRAMS += reactors
+
+reactors_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+reactors_SOURCES = \
+ test_reactors.cpp
+
+reactors_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Makefile.Reactor_Misc_Signals_1.am
+noinst_PROGRAMS += signals_1
+
+signals_1_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+signals_1_SOURCES = \
+ test_signals_1.cpp
+
+signals_1_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Makefile.Reactor_Misc_Signals_2.am
+noinst_PROGRAMS += signals_2
+
+signals_2_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+signals_2_SOURCES = \
+ test_signals_2.cpp
+
+signals_2_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Makefile.Reactor_Misc_Timer_Queue.am
+noinst_PROGRAMS += timer_queue
+
+timer_queue_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+timer_queue_SOURCES = \
+ test_timer_queue.cpp
+
+timer_queue_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Clean up template repositories, etc.
+clean-local:
+ -rm -f *~ *.bak *.rpo *.sym lib*.*_pure_* core core.*
+ -rm -f gcctemp.c gcctemp so_locations *.ics
+ -rm -rf cxx_repository ptrepository ti_files
+ -rm -rf templateregistry ir.out
+ -rm -rf ptrepository SunWS_cache Templates.DB
diff --git a/ACE/examples/Reactor/Misc/Reactor_Misc.mpc b/ACE/examples/Reactor/Misc/Reactor_Misc.mpc
new file mode 100644
index 00000000000..c056a909bd8
--- /dev/null
+++ b/ACE/examples/Reactor/Misc/Reactor_Misc.mpc
@@ -0,0 +1,57 @@
+// -*- MPC -*-
+// $Id$
+
+project(*event_handler_t) : aceexe {
+ exename = event_handler_t
+ Source_Files {
+ test_event_handler_t.cpp
+ }
+}
+project(*demuxing) : aceexe {
+ exename = demuxing
+ Source_Files {
+ test_demuxing.cpp
+ }
+}
+project(*early_timeouts) : aceexe {
+ exename = early_timeouts
+ Source_Files {
+ test_early_timeouts.cpp
+ }
+}
+project(*notification) : aceexe {
+ exename = notification
+ Source_Files {
+ notification.cpp
+ }
+}
+project(*pingpong) : aceexe {
+ exename = pingpong
+ Source_Files {
+ pingpong.cpp
+ }
+}
+project(*reactors) : aceexe {
+ exename = reactors
+ Source_Files {
+ test_reactors.cpp
+ }
+}
+project(*signals_1) : aceexe {
+ exename = signals_1
+ Source_Files {
+ test_signals_1.cpp
+ }
+}
+project(*signals_2) : aceexe {
+ exename = signals_2
+ Source_Files {
+ test_signals_2.cpp
+ }
+}
+project(*timer_queue) : aceexe {
+ exename = timer_queue
+ Source_Files {
+ test_timer_queue.cpp
+ }
+}
diff --git a/ACE/examples/Reactor/Misc/notification.cpp b/ACE/examples/Reactor/Misc/notification.cpp
new file mode 100644
index 00000000000..a04663b28ad
--- /dev/null
+++ b/ACE/examples/Reactor/Misc/notification.cpp
@@ -0,0 +1,385 @@
+// $Id$
+
+#include "ace/OS_NS_unistd.h"
+#include "ace/Service_Config.h"
+#include "ace/Reactor.h"
+#include "ace/Thread_Manager.h"
+#include "ace/Thread.h"
+#include "ace/Signal.h"
+
+ACE_RCSID(Misc, notification, "$Id$")
+
+#if defined (ACE_HAS_THREADS)
+#if defined (CHORUS)
+// Chorus does not have signal, so we'll stop after a number of rounds.
+#define MAX_ITERATIONS 3
+#else
+#define MAX_ITERATIONS 10000
+#endif /* CHORUS */
+
+class Thread_Handler : public ACE_Event_Handler
+{
+ // = TITLE
+ // Illustrate how the ACE_Reactor's thread-safe event notification
+ // mechanism works.
+ //
+ // = DESCRIPTION
+ // Handle timeouts in the main thread via the ACE_Reactor and I/O
+ // events in a separate thread. Just before the separate I/O
+ // thread exits it notifies the ACE_Reactor in the main thread
+ // using the ACE_Reactor's notification mechanism.
+public:
+ Thread_Handler (long delay,
+ long interval,
+ size_t n_threads,
+ size_t max_iterations);
+ // Constructor.
+
+ Thread_Handler (size_t id,
+ size_t max_iterations);
+
+ ~Thread_Handler (void);
+ // Destructor.
+
+ virtual int handle_signal (int signum,
+ siginfo_t * = 0,
+ ucontext_t * = 0);
+ // Handle signals.
+
+ virtual int handle_exception (ACE_HANDLE);
+ // Print data from main thread.
+
+ virtual int handle_output (ACE_HANDLE);
+ // Print data from main thread.
+
+ virtual int handle_timeout (const ACE_Time_Value &,
+ const void *);
+ // Handle timeout events in the main thread.
+
+ virtual int handle_input (ACE_HANDLE);
+ // General notification messages to the Reactor.
+
+ virtual int notify (ACE_Time_Value *tv = 0);
+ // Perform notifications.
+
+ virtual int svc (void);
+ // Handle I/O events in a separate threads.
+
+private:
+ static void *svc_run (void *);
+ // Glues C++ to C thread library functions.
+
+ size_t id_;
+ // ID passed in by Thread_Handler constructor.
+
+ size_t iterations_;
+
+ static sig_atomic_t shutdown_;
+ // Shutting down.
+
+ // = Timing variables.
+ // Delay factor for timer-driven I/O.
+ static ACE_Time_Value delay_;
+
+ // Interval factor for Event_Handler timer.
+ static ACE_Time_Value interval_;
+};
+
+// Shutdown flag.
+sig_atomic_t Thread_Handler::shutdown_ = 0;
+
+// Delay factor for timer-driven I/O.
+ACE_Time_Value Thread_Handler::delay_;
+
+// Interval factor for Event_Handler timer.
+ACE_Time_Value Thread_Handler::interval_;
+
+Thread_Handler::Thread_Handler (size_t id,
+ size_t max_iterations)
+ : id_ (id),
+ iterations_ (max_iterations)
+{
+}
+
+Thread_Handler::~Thread_Handler (void)
+{
+ // Cleanup resources so that we don't crash and burn when shutdown.
+ ACE_Event_Handler::remove_stdin_handler (ACE_Reactor::instance (),
+ ACE_Thread_Manager::instance ());
+ ACE_Reactor::instance ()->cancel_timer (this);
+}
+
+Thread_Handler::Thread_Handler (
+ long delay,
+ long interval,
+ size_t n_threads,
+ size_t max_iterations)
+ : iterations_ (max_iterations)
+{
+ ACE_Sig_Set sig_set;
+
+ sig_set.sig_add (SIGQUIT);
+ sig_set.sig_add (SIGINT);
+
+ delay_.set (delay);
+ interval_.set (interval);
+ this->id_ = 0;
+
+ if (ACE_Event_Handler::register_stdin_handler (this,
+ ACE_Reactor::instance (),
+ ACE_Thread_Manager::instance ()) == -1)
+ ACE_ERROR ((LM_ERROR,
+ "%p\n",
+ "register_stdin_handler"));
+ else if (ACE_Reactor::instance ()->register_handler (sig_set,
+ this) == -1)
+ ACE_ERROR ((LM_ERROR,
+ "(%t) %p\n",
+ "register_handler"));
+ else if (ACE_Reactor::instance ()->schedule_timer
+ (this,
+ 0,
+ Thread_Handler::delay_,
+ Thread_Handler::interval_) == -1)
+ ACE_ERROR ((LM_ERROR,
+ "(%t) %p\n",
+ "schedule_timer"));
+
+ // Set up this thread's signal mask to block all the signal in the
+ // <sig_set>, which is inherited by the threads it spawns.
+ ACE_Sig_Guard guard (&sig_set);
+
+ // Create N new threads of control Thread_Handlers.
+
+ for (size_t i = 0; i < n_threads; i++)
+ {
+ Thread_Handler *th;
+
+ ACE_NEW (th,
+ Thread_Handler (i + 1,
+ this->iterations_));
+
+ if (ACE_Thread::spawn (reinterpret_cast<ACE_THR_FUNC> (&Thread_Handler::svc_run),
+ reinterpret_cast<void *> (th),
+ THR_NEW_LWP | THR_DETACHED) != 0)
+ ACE_ERROR ((LM_ERROR,
+ "%p\n",
+ "ACE_Thread::spawn"));
+ }
+
+ // The destructor of <guard> unblocks the signal set so that only
+ // this thread receives them!
+}
+
+int
+Thread_Handler::notify (ACE_Time_Value *timeout)
+{
+ // Just do something to test the ACE_Reactor's multi-thread
+ // capabilities...
+
+ if (ACE_Reactor::instance ()->notify
+ (this,
+ ACE_Event_Handler::EXCEPT_MASK,
+ timeout) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "(%t) %p\n",
+ "notification::notify:exception"),
+ -1);
+ else if (ACE_Reactor::instance ()->notify
+ (this,
+ ACE_Event_Handler::WRITE_MASK,
+ timeout) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "(%t) %p\n",
+ "notification::notify:write"),
+ -1);
+ return 0;
+}
+
+// Test stdin handling that uses <select> to demultiplex HANDLEs.
+// Input is only handled by the main thread.
+
+int
+Thread_Handler::handle_input (ACE_HANDLE handle)
+{
+ char buf[BUFSIZ];
+ ssize_t n = ACE_OS::read (handle, buf, sizeof buf);
+
+ if (n > 0)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ "input to (%t) %*s",
+ n,
+ buf));
+
+ ACE_DEBUG ((LM_DEBUG,
+ "%d more input to kill\n",
+ this->iterations_));
+
+ // Only wait up to 10 milliseconds to notify the Reactor.
+ ACE_Time_Value timeout (0,
+ 10 * 1000);
+
+ if (this->notify (&timeout) == -1)
+ ACE_ERROR ((LM_DEBUG,
+ "(%t), %p\n",
+ "notification::handle_input:notify"));
+ return 0;
+ }
+ else
+ return -1;
+}
+
+// Perform a task that will test the ACE_Reactor's multi-threading
+// capabilities in separate threads.
+
+int
+Thread_Handler::svc (void)
+{
+ ACE_Time_Value sleep_timeout (0,
+ // Transform this into microseconds and divide by 2.
+ (Thread_Handler::interval_.sec () * ACE_ONE_SECOND_IN_USECS) / 2);
+
+ for (int i = this->iterations_;
+ i > 0;
+ --i)
+ {
+ if (this->shutdown_ != 0)
+ break;
+
+ // Block for delay_.secs () / 2, then notify the Reactor.
+ ACE_OS::sleep (sleep_timeout);
+
+ // Wait up to 10 milliseconds to notify the Reactor.
+ ACE_Time_Value timeout (0,
+ 10 * 1000);
+ if (this->notify (&timeout) == -1)
+ ACE_ERROR ((LM_ERROR,
+ "(%t) %p\n",
+ "notify"));
+ }
+
+ ACE_Reactor::instance ()->remove_handler (this,
+ ALL_EVENTS_MASK);
+ ACE_DEBUG ((LM_DEBUG,
+ "(%t) exiting svc\n"));
+ return 0;
+}
+
+// Test signal handling.
+
+int
+Thread_Handler::handle_signal (int signum, siginfo_t *, ucontext_t *)
+{
+ // @@ Note that this code is not portable to all OS platforms since
+ // it uses print statements within signal handler context.
+ ACE_DEBUG ((LM_DEBUG,
+ "(%t) received signal %S\n",
+ signum));
+
+ switch (signum)
+ {
+ case SIGINT:
+ case SIGQUIT:
+ ACE_ERROR ((LM_ERROR,
+ "(%t) ******************** shutting down %n on signal %S\n",
+ signum));
+ this->shutdown_ = 1;
+ ACE_Reactor::end_event_loop();
+ }
+ return 0;
+}
+
+int
+Thread_Handler::handle_timeout (const ACE_Time_Value &time, const void *)
+{
+ ACE_DEBUG ((LM_DEBUG,
+ "(%t) received timeout at (%u, %u), iterations = %d\n",
+ time.sec (),
+ time.usec (),
+ this->iterations_));
+
+ if (--this->iterations_ <= 0
+ || Thread_Handler::interval_.sec () == 0)
+ ACE_Reactor::end_event_loop ();
+
+ return 0;
+}
+
+// Called by the ACE_Reactor when it receives a notification.
+
+int
+Thread_Handler::handle_exception (ACE_HANDLE)
+{
+ ACE_DEBUG ((LM_DEBUG,
+ "(%t) exception to id %d, iteration = %d\n",
+ this->id_,
+ this->iterations_));
+ return 0;
+}
+
+// Called by the ACE_Reactor when it receives a notification.
+
+int
+Thread_Handler::handle_output (ACE_HANDLE)
+{
+ ACE_DEBUG ((LM_DEBUG,
+ "(%t) output to id %d, iteration = %d\n",
+ this->id_,
+ // This decrement must come last since
+ // <handle_exception> is called before <handle_output>!
+ this->iterations_--));
+ return 0;
+}
+
+// "Shim" function that integrates C thread API with C++.
+
+void *
+Thread_Handler::svc_run (void *eh)
+{
+ Thread_Handler *this_handler =
+ reinterpret_cast<Thread_Handler *> (eh);
+
+ if (this_handler->svc () == 0)
+ return 0;
+ else
+ return reinterpret_cast<void *> (-1);
+}
+
+int
+ACE_TMAIN (int argc, ACE_TCHAR *argv[])
+{
+ ACE_LOG_MSG->open (argv[0]);
+
+ if (argc < 4)
+ {
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("usage: %s delay interval n_threads [iterations]\n"),
+ argv[0]));
+ ACE_OS::exit (1);
+ }
+
+ int delay = ACE_OS::atoi (argv[1]);
+ int interval = ACE_OS::atoi (argv[2]);
+ size_t n_threads = ACE_OS::atoi (argv[3]);
+ size_t max_iterations = argc > 4 ? ACE_OS::atoi (argv[4]) : MAX_ITERATIONS;
+
+ Thread_Handler thr_handler (delay,
+ interval,
+ n_threads,
+ max_iterations);
+
+ ACE_Reactor::instance ()->run_reactor_event_loop ();
+
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("exiting from main\n")));
+ return 0;
+}
+#else
+int
+main (int, char *[])
+{
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "threads must be supported to run this application\n"), -1);
+}
+#endif /* ACE_HAS_THREADS */
diff --git a/ACE/examples/Reactor/Misc/pingpong.cpp b/ACE/examples/Reactor/Misc/pingpong.cpp
new file mode 100644
index 00000000000..f4a3bc0630e
--- /dev/null
+++ b/ACE/examples/Reactor/Misc/pingpong.cpp
@@ -0,0 +1,302 @@
+// $Id$
+
+/* Simple program that illustrates many features of the ACE_Reactor:
+
+ 1. I/O event demultiplexing
+ 2. Signal-based demultiplexing
+ 3. Timer-based demultiplexing
+
+ To test this program, compile it and then execute it as follows:
+
+ % ./pingpong hello
+
+ You should see lots of the following output:
+
+ writing <4> [7860]
+ writing <4> [7860]
+ writing <4> [7860]
+ writing <4> [7860]
+ reading <5> (7860) [1] = hello
+ writing <4> [7860]
+ writing <5> [7861]
+ reading <4> (7861) [2] = hello
+ reading <5> (7860) [2] = hello
+ writing <4> [7860]
+ writing <5> [7861]
+ reading <4> (7861) [3] = hello
+ reading <5> (7860) [3] = hello
+
+ After 10 seconds you'll see the following:
+
+ ./pingpong: shutting down tester (pid = 7861)
+ ./pingpong: shutting down tester (pid = 7860)
+
+ and the program will stop. If you'd like to
+ stop it earlier, just hit the control-C sequence
+ and you'll see the same messages. */
+
+#include "ace/Reactor.h"
+#include "ace/Pipe.h"
+#include "ace/Log_Msg.h"
+#include "ace/ACE.h"
+#include "ace/Test_and_Set.h"
+#include "ace/OS_NS_string.h"
+#include "ace/Null_Mutex.h"
+#include "ace/OS_NS_unistd.h"
+#if defined (ACE_WIN32) || defined (CHORUS)
+# include "ace/Barrier.h"
+# include "ace/Thread.h"
+#endif
+
+ACE_RCSID(Misc, pingpong, "$Id$")
+
+class Ping_Pong : public ACE_Test_and_Set<ACE_Null_Mutex, sig_atomic_t>
+{
+public:
+ Ping_Pong (char b[], ACE_HANDLE f);
+ virtual ACE_HANDLE get_handle (void) const;
+ virtual int handle_input (ACE_HANDLE);
+ virtual int handle_output (ACE_HANDLE);
+ virtual int handle_timeout (const ACE_Time_Value &,
+ const void *);
+ virtual int handle_close (ACE_HANDLE handle,
+ ACE_Reactor_Mask close_mask);
+private:
+ char buf_[BUFSIZ];
+ // Buffer to send.
+
+ size_t buflen_;
+ // Length of the buffer to send.
+
+ int pid_;
+ // Process ID.
+
+ ACE_HANDLE handle_;
+ // Open handle.
+};
+
+Ping_Pong::Ping_Pong (char b[], ACE_HANDLE f)
+ : buflen_ (ACE_OS::strlen (b) + 1 + (2 * sizeof (int))),
+ pid_ (ACE_OS::getpid ()),
+ handle_ (f)
+{
+ *((int *) this->buf_) = (int) this->pid_;
+ *((int *) (this->buf_ + sizeof (int))) = 0;
+ ACE_OS::strcpy (this->buf_ + (2 * sizeof (int)), b);
+ this->buf_[this->buflen_ - 1] = '\n';
+ this->buf_[this->buflen_] = '\0';
+}
+
+ACE_HANDLE
+Ping_Pong::get_handle (void) const
+{
+ return this->handle_;
+}
+
+int
+Ping_Pong::handle_close (ACE_HANDLE,
+ ACE_Reactor_Mask)
+{
+ delete this; // Cleanup when we're removed from the reactor.
+ return 0;
+}
+
+int
+Ping_Pong::handle_input (ACE_HANDLE)
+{
+#if defined (ACE_HAS_STREAM_PIPES)
+ // We can rely on record-oriented reads...
+
+ ssize_t n = ACE::recv (this->handle_, this->buf_, this->buflen_);
+
+ if (n != (ssize_t) this->buflen_)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("(%P|%t) reading [%d] %p\n"),
+ handle_,
+ ACE_TEXT ("read")),
+ -1);
+
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("(%P|%t) reading <%d> (%d) [%d] = %C\n"),
+ this->handle_,
+ *(int *) this->buf_,
+ *(int *) (this->buf_ + sizeof (int)),
+ this->buf_ + (2 * sizeof (int))));
+#else
+ ssize_t n = ACE::recv (this->handle_,
+ this->buf_,
+ this->buflen_);
+ if (n == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("[%d] %p\n"),
+ handle_,
+ ACE_TEXT ("read")),
+ -1);
+ n -= (2 * sizeof (int));
+ char *buf = this->buf_ + (2 * sizeof (int));
+
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("(%P|%t) reading <%d> = %*C\n"),
+ this->handle_,
+ n,
+ buf));
+#endif /* ACE_HAS_STREAM_PIPES */
+ return 0;
+}
+
+int
+Ping_Pong::handle_output (ACE_HANDLE)
+{
+#if defined (ACE_HAS_STREAM_PIPES)
+ // We can rely on record-oriented reads...
+
+ (*(int *) (this->buf_)) = this->pid_;
+ (*(int *) (this->buf_ + sizeof (int)))++;
+ if (ACE::send (this->handle_,
+ this->buf_,
+ this->buflen_) == -1)
+ return -1;
+ else
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("(%P|%t) writing <%d> [%d]\n"),
+ this->handle_,
+ this->pid_));
+ return 0;
+ }
+#else
+ if (ACE::send (this->handle_,
+ this->buf_,
+ this->buflen_) == -1)
+ return -1;
+ else
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("(%P|%t) writing <%d>\n"),
+ this->handle_));
+ return 0;
+ }
+#endif /* ACE_HAS_STREAM_PIPES */
+}
+
+int
+Ping_Pong::handle_timeout (const ACE_Time_Value &,
+ const void *)
+{
+ this->set (1);
+ return 0;
+}
+
+// Contains the string to "pingpong" back and forth...
+static ACE_TCHAR *string_name;
+
+// Wait for 10 seconds and then shut down.
+static const ACE_Time_Value SHUTDOWN_TIME (10);
+
+static void
+run_svc (ACE_HANDLE handle)
+{
+ Ping_Pong *callback = 0;
+ ACE_NEW (callback,
+ Ping_Pong (ACE_TEXT_ALWAYS_CHAR (string_name),
+ handle));
+
+ ACE_Reactor reactor;
+
+ // Register the callback object for the various I/O, signal, and
+ // timer-based events.
+
+ if (reactor.register_handler (callback,
+ ACE_Event_Handler::READ_MASK
+ | ACE_Event_Handler::WRITE_MASK) == -1
+#if !defined (CHORUS)
+ || reactor.register_handler (SIGINT,
+ callback) == -1
+#endif /* CHORUS */
+ || reactor.schedule_timer (callback,
+ 0,
+ SHUTDOWN_TIME) == -1)
+ {
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("reactor")));
+ ACE_OS::exit (1);
+ }
+
+ // Main event loop (one per process).
+
+ while (callback->is_set () == 0)
+ if (reactor.handle_events () == -1)
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("handle_events")));
+}
+
+#if defined (ACE_WIN32) || defined (CHORUS)
+static ACE_Barrier barrier (3);
+
+static void *
+worker (void *arg)
+{
+ ACE_HANDLE handle = (ACE_HANDLE) arg;
+
+ run_svc (handle);
+
+ // Wait for the threads to exit.
+ barrier.wait ();
+
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("(%P|%t) %n: shutting down tester\n")));
+ return 0;
+}
+#endif /* ACE_WIN32 */
+
+int
+ACE_TMAIN (int argc, ACE_TCHAR *argv[])
+{
+ if (argc != 2)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("usage: pingpong <string>\n")),
+ -1);
+
+ ACE_LOG_MSG->open (argv[0]);
+
+ string_name = argv[1];
+
+ ACE_HANDLE handles[2];
+
+ // Create a pipe and initialize the handles.
+ ACE_Pipe pipe (handles);
+
+#if defined (ACE_WIN32) || defined (CHORUS)
+ if (ACE_Thread::spawn (ACE_THR_FUNC (worker),
+ (void *) handles[0],
+ THR_DETACHED) == -1
+ || ACE_Thread::spawn (ACE_THR_FUNC (worker),
+ (void *) handles[1],
+ THR_DETACHED) == -1)
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("%p\n%a"),
+ ACE_TEXT ("spawn"),
+ 1));
+ barrier.wait ();
+#else
+ pid_t pid = ACE_OS::fork (argv[0]);
+
+ if (pid == -1)
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("%p\n%a"),
+ ACE_TEXT ("fork"),
+ 1));
+ run_svc (handles[pid == 0]);
+
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("(%P|%t) %n: shutting down tester\n")));
+#endif /* ACE_WIN32 */
+
+ if (pipe.close () == -1)
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("close")));
+ return 0;
+}
diff --git a/ACE/examples/Reactor/Misc/test_demuxing.cpp b/ACE/examples/Reactor/Misc/test_demuxing.cpp
new file mode 100644
index 00000000000..6badd849757
--- /dev/null
+++ b/ACE/examples/Reactor/Misc/test_demuxing.cpp
@@ -0,0 +1,384 @@
+// $Id$
+
+// Perform an extensive test of all the ACE_Reactor's event handler
+// dispatching mechanisms. These mechanisms illustrate how I/O,
+// timeout, and signal events, as well as ACE_Message_Queues, can all
+// be handled within the same demultiplexing and dispatching
+// framework. In addition, this example illustrates how to use the
+// ACE_Reactor for devices that perform I/O via signals (such as SVR4
+// message queues).
+
+#include "ace/ACE.h"
+#include "ace/Service_Config.h"
+#include "ace/Reactor.h"
+#include "ace/Task.h"
+#include "ace/Reactor_Notification_Strategy.h"
+#include "ace/Signal.h"
+#include "ace/OS_NS_fcntl.h"
+#include "ace/OS_NS_unistd.h"
+
+ACE_RCSID(Misc, test_demuxing, "$Id$")
+
+// Default is to have a 2 second timeout.
+static int timeout = 2;
+
+class Sig_Handler : public ACE_Event_Handler
+{
+ // = TITLE
+ // This class illustrates how to handle signal-driven I/O using
+ // the <ACE_Reactor> framework. Note that signals may be caught
+ // and processed without requiring the use of global signal
+ // handler functions or global signal handler data.
+public:
+ Sig_Handler (void);
+ virtual ACE_HANDLE get_handle (void) const;
+ virtual int handle_input (ACE_HANDLE);
+ virtual int shutdown (ACE_HANDLE, ACE_Reactor_Mask);
+ virtual int handle_signal (int signum, siginfo_t * = 0,
+ ucontext_t * = 0);
+
+private:
+ ACE_HANDLE handle_;
+};
+
+// A dummy_handle is required to reserve a slot in the ACE_Reactor's
+// descriptor table.
+
+Sig_Handler::Sig_Handler (void)
+{
+ // Assign the Sig_Handler a dummy I/O descriptor. Note that even
+ // though we open this file "Write Only" we still need to use the
+ // ACE_Event_Handler::NULL_MASK when registering this with the
+ // ACE_Reactor (see below).
+ this->handle_ = ACE_OS::open (ACE_DEV_NULL, O_WRONLY);
+ ACE_ASSERT (this->handle_ != ACE_INVALID_HANDLE);
+
+ // Register signal handler object. Note that NULL_MASK is used to
+ // keep the ACE_Reactor from calling us back on the "/dev/null"
+ // descriptor. NULL_MASK just reserves a "slot" in the Reactor's
+ // internal demuxing table, but doesn't cause it to dispatch the
+ // event handler directly. Instead, we use the signal handler to do
+ // this.
+ ACE_Reactor_Mask mask = ACE_Event_Handler::NULL_MASK;
+ if (ACE_Reactor::instance ()->register_handler
+ (this,
+ mask) == -1)
+ ACE_ERROR ((LM_ERROR,
+ "%p\n%a",
+ "register_handler",
+ 1));
+
+ // Create a sigset_t corresponding to the signals we want to catch.
+ ACE_Sig_Set sig_set;
+
+ sig_set.sig_add (SIGINT);
+ sig_set.sig_add (SIGQUIT);
+ sig_set.sig_add (SIGALRM);
+
+ // Register the signal handler object to catch the signals.
+ if (ACE_Reactor::instance ()->register_handler
+ (sig_set, this) == -1)
+ ACE_ERROR ((LM_ERROR,
+ "%p\n%a",
+ "register_handler",
+ 1));
+}
+
+// Called by the ACE_Reactor to extract the handle.
+
+ACE_HANDLE
+Sig_Handler::get_handle (void) const
+{
+ return this->handle_;
+}
+
+// In a real application, this method would be where the read on the
+// signal-driven I/O device would occur asynchronously. For now we'll
+// just print a greeting to let you know that everything is working
+// properly!
+
+int
+Sig_Handler::handle_input (ACE_HANDLE)
+{
+ ACE_DEBUG ((LM_DEBUG,
+ "(%t) handling asynchonrous input...\n"));
+ return 0;
+}
+
+// In a real application, this method would do any cleanup activities
+// required when shutting down the I/O device.
+
+int
+Sig_Handler::shutdown (ACE_HANDLE, ACE_Reactor_Mask)
+{
+ ACE_DEBUG ((LM_DEBUG,
+ "(%t) closing down Sig_Handler...\n"));
+ return 0;
+}
+
+// This method handles all the signals that are being caught by this
+// object. In our simple example, we are simply catching SIGALRM,
+// SIGINT, and SIGQUIT. Anything else is logged and ignored. Note
+// that the ACE_Reactor's signal handling mechanism eliminates the
+// need to use global signal handler functions and data.
+
+int
+Sig_Handler::handle_signal (int signum, siginfo_t *, ucontext_t *)
+{
+ switch (signum)
+ {
+#if !defined (ACE_WIN32)
+ case SIGALRM:
+ // Rearm the alarm.
+ ACE_OS::alarm (4);
+ break;
+#endif /* !ACE_WIN32 */
+ case SIGINT:
+ // Tell the ACE_Reactor to enable the ready bit for
+ // this->handle_. The ACE_Reactor will subsequently call the
+ // <Sig_Handler::handle_input> method from within its event
+ // loop, i.e., the behavior triggered by the signal is handled
+ // in the main event loop, rather than in the signal handler.
+ return ACE_Reactor::instance ()->ready_ops
+ (this->handle_,
+ ACE_Event_Handler::READ_MASK,
+ ACE_Reactor::ADD_MASK);
+#if defined (ACE_WIN32)
+ case SIGTERM:
+#else
+ case SIGQUIT:
+#endif /* ACE_WIN32 */
+ ACE_Reactor::end_event_loop ();
+ break;
+ default:
+ ACE_ERROR_RETURN ((LM_ERROR, "invalid signal"), -1);
+ break;
+ /* NOTREACHED */
+ }
+ return 0;
+}
+
+class STDIN_Handler : public ACE_Event_Handler
+{
+ // = TITLE
+ // This class illustrates that the ACE_Reactor can handle signals,
+ // STDIO, and timeouts using the same mechanisms.
+public:
+ STDIN_Handler (void);
+ ~STDIN_Handler (void);
+ virtual int handle_input (ACE_HANDLE);
+ virtual int handle_timeout (const ACE_Time_Value &,
+ const void *arg);
+};
+
+STDIN_Handler::STDIN_Handler (void)
+{
+ if (ACE_Event_Handler::register_stdin_handler (this,
+ ACE_Reactor::instance (),
+ ACE_Thread_Manager::instance ()) == -1)
+ ACE_ERROR ((LM_ERROR,
+ "%p\n",
+ "register_stdin_handler"));
+
+ // Register the <STDIN_Handler> to be dispatched once every
+ // <timeout> seconds starting in <timeout> seconds. This example
+ // uses the "interval timer" feature of the <ACE_Reactor>'s timer
+ // queue.
+ else if (ACE_Reactor::instance ()->schedule_timer
+ (this,
+ 0,
+ ACE_Time_Value (timeout),
+ ACE_Time_Value (timeout)) == -1)
+ ACE_ERROR ((LM_ERROR,
+ "%p\n%a",
+ "schedule_timer",
+ 1));
+}
+
+STDIN_Handler::~STDIN_Handler (void)
+{
+ if (ACE_Event_Handler::remove_stdin_handler (ACE_Reactor::instance (),
+ ACE_Thread_Manager::instance ()) == -1)
+ ACE_ERROR ((LM_ERROR,
+ "%p\n",
+ "remove_stdin_handler"));
+ else if (ACE_Reactor::instance ()->cancel_timer
+ (this) == -1)
+ ACE_ERROR ((LM_ERROR,
+ "%p\n%a",
+ "cancel_timer",
+ 1));
+}
+
+int
+STDIN_Handler::handle_timeout (const ACE_Time_Value &tv,
+ const void *)
+{
+ ACE_DEBUG ((LM_DEBUG,
+ "(%t) timeout occurred at %d sec, %d usec\n",
+ tv.sec (),
+ tv.usec ()));
+ return 0;
+}
+
+// Read from input handle and write to stdout handle.
+
+int
+STDIN_Handler::handle_input (ACE_HANDLE handle)
+{
+ char buf[BUFSIZ];
+ ssize_t n = ACE_OS::read (handle, buf, sizeof buf);
+
+ switch (n)
+ {
+ case -1:
+ if (errno == EINTR)
+ return 0;
+ /* NOTREACHED */
+ else
+ ACE_ERROR ((LM_ERROR,
+ "%p\n",
+ "read"));
+ /* FALLTHROUGH */
+ case 0:
+ ACE_Reactor::end_event_loop ();
+ break;
+ default:
+ {
+ ssize_t result = ACE::write_n (ACE_STDOUT, buf, n);
+
+ if (result != n)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%p\n",
+ "write"),
+ result == -1 && errno == EINTR ? 0 : -1);
+ }
+ }
+ return 0;
+}
+
+class Message_Handler : public ACE_Task <ACE_SYNCH>
+{
+public:
+ Message_Handler (void);
+
+ virtual int handle_input (ACE_HANDLE);
+ // Called back within the context of the <ACE_Reactor> Singleton to
+ // dequeue and process the message on the <ACE_Message_Queue>.
+
+ virtual int svc (void);
+ // Run the "event-loop" periodically putting messages to our
+ // internal <Message_Queue> that we inherit from <ACE_Task>.
+
+private:
+ ACE_Reactor_Notification_Strategy notification_strategy_;
+ // This strategy will notify the <ACE_Reactor> Singleton when a new
+ // message is enqueued.
+};
+
+Message_Handler::Message_Handler (void)
+ : notification_strategy_ (ACE_Reactor::instance (),
+ this,
+ ACE_Event_Handler::READ_MASK)
+{
+ // Set this to the Reactor notification strategy.
+ this->msg_queue ()->notification_strategy (&this->notification_strategy_);
+
+ if (this->activate ())
+ ACE_ERROR ((LM_ERROR,
+ "%p\n",
+ "activate"));
+}
+
+int
+Message_Handler::svc (void)
+{
+ for (int i = 0;; i++)
+ {
+ ACE_Message_Block *mb;
+
+ ACE_NEW_RETURN (mb,
+ ACE_Message_Block (1),
+ 0);
+
+ mb->msg_priority (i);
+ ACE_OS::sleep (1);
+
+ // Note that this putq() call with automagically invoke the
+ // notify() hook of our ACE_Reactor_Notification_Strategy,
+ // thereby informing the <ACE_Reactor> Singleton to call our
+ // <handle_input> method.
+ if (this->putq (mb) == -1)
+ {
+ if (errno == ESHUTDOWN)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "(%t) queue is deactivated"), 0);
+ else
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "(%t) %p\n",
+ "putq"),
+ -1);
+ }
+ }
+
+ ACE_NOTREACHED (return 0);
+}
+
+int
+Message_Handler::handle_input (ACE_HANDLE)
+{
+ ACE_DEBUG ((LM_DEBUG,
+ "(%t) Message_Handler::handle_input\n"));
+
+ ACE_Message_Block *mb;
+
+ if (this->getq (mb, (ACE_Time_Value *) &ACE_Time_Value::zero) == -1)
+ ACE_ERROR ((LM_ERROR,
+ "(%t) %p\n",
+ "dequeue_head"));
+ else
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ "(%t) priority = %d\n",
+ mb->msg_priority ()));
+ mb->release ();
+ }
+
+ return 0;
+}
+
+int
+ACE_TMAIN (int argc, ACE_TCHAR *argv[])
+{
+ ACE_Service_Config daemon (argv [0]);
+
+ // Optionally start the alarm.
+ if (argc > 1)
+ {
+ ACE_OS::alarm (4);
+ timeout = ACE_OS::atoi (argv[1]);
+ }
+
+ // Signal handler.
+ Sig_Handler sh;
+
+ // Define an I/O handler object.
+ STDIN_Handler ioh;
+
+ // Define a message handler.
+ Message_Handler mh;
+
+ // Loop handling signals and I/O events until SIGQUIT occurs.
+
+ while (ACE_Reactor::instance ()->event_loop_done () == 0)
+ ACE_Reactor::instance ()->run_reactor_event_loop ();
+
+ // Deactivate the message queue.
+ mh.msg_queue ()->deactivate ();
+
+ // Wait for the thread to exit.
+ ACE_Thread_Manager::instance ()->wait ();
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("(%t) leaving main\n")));
+ return 0;
+}
diff --git a/ACE/examples/Reactor/Misc/test_early_timeouts.cpp b/ACE/examples/Reactor/Misc/test_early_timeouts.cpp
new file mode 100644
index 00000000000..4c7193d9a67
--- /dev/null
+++ b/ACE/examples/Reactor/Misc/test_early_timeouts.cpp
@@ -0,0 +1,114 @@
+// $Id$
+
+// ================================================================
+//
+// = LIBRARY
+// examples/Reactor/Misc/
+//
+// = FILENAME
+// test_early_timeouts.cpp
+//
+// = DESCRIPTION
+// On some platforms, select() returns before the time value
+// specified. This tests counts the number of times this happens
+// and the max early timeout.
+//
+// = AUTHOR
+// Irfan Pyarali <irfan@cs.wustl.edu>
+//
+// ================================================================
+
+#include "ace/Handle_Set.h"
+#include "ace/Pipe.h"
+#include "ace/Log_Msg.h"
+#include "ace/Time_Value.h"
+#include "ace/OS_NS_sys_time.h"
+#include "ace/OS_NS_sys_select.h"
+
+ACE_RCSID(Misc, test_early_timeouts, "$Id$")
+
+int
+ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ // Mumber of seconds this test should run
+ int runtime_in_seconds = 10;
+
+ // Iterations
+ int iterations = runtime_in_seconds * 10;
+
+ // 100 millisecond timeout
+ ACE_Time_Value timeout (0, 100000);
+
+ // Time before starting select
+ ACE_Time_Value starting_time_of_day;
+
+ // Time before starting select
+ ACE_Time_Value ending_time_of_day;
+
+ // Number of times the timer expired early
+ int no_of_early_timers = 0;
+
+ // Maximum early timeout
+ ACE_Time_Value maximum_early_timeout;
+
+ //
+ // Dummy handle and handle set
+ // Note that some OS do not like "empty selects"
+ //
+
+ // Dummy handle set
+ ACE_Handle_Set dummy_handle_set;
+
+ // Dummy pipe
+ ACE_Pipe dummy_pipe;
+ int result = dummy_pipe.open ();
+ ACE_ASSERT (result == 0);
+ ACE_UNUSED_ARG (result); // To avoid compile warning with ACE_NDEBUG.
+
+ for (int i = 1; i <= iterations; i++)
+ {
+ // Add dummy handle to dummy set
+ dummy_handle_set.set_bit (dummy_pipe.read_handle ());
+
+ // Note the time before select
+ starting_time_of_day = ACE_OS::gettimeofday ();
+
+ // Wait for timeout
+ result = ACE_OS::select ((int) dummy_pipe.read_handle (), dummy_handle_set, 0, 0, &timeout);
+ ACE_ASSERT (result == 0);
+
+ // Note the time after select
+ ending_time_of_day = ACE_OS::gettimeofday ();
+
+ // Expected ending time
+ ACE_Time_Value expected_ending_time_of_day =
+ starting_time_of_day + timeout;
+
+ // If the timer expired early
+ if (ending_time_of_day < expected_ending_time_of_day)
+ {
+ // How early
+ ACE_Time_Value early_timeout = expected_ending_time_of_day - ending_time_of_day;
+
+ // Increment number of early timers
+ no_of_early_timers++;
+
+ // Check max early timeout
+ if (early_timeout > maximum_early_timeout)
+ {
+ maximum_early_timeout = early_timeout;
+ }
+ }
+ }
+
+ ACE_DEBUG ((LM_DEBUG,
+ "There were %d early timers out of %d calls to select() (%f%%)\n"
+ "The max early timeout was: %dsec %dusec\n",
+ no_of_early_timers,
+ iterations,
+ float (no_of_early_timers) / iterations * 100,
+ maximum_early_timeout.sec (),
+ maximum_early_timeout.usec ()));
+
+ return 0;
+}
diff --git a/ACE/examples/Reactor/Misc/test_event_handler_t.cpp b/ACE/examples/Reactor/Misc/test_event_handler_t.cpp
new file mode 100644
index 00000000000..4261859784e
--- /dev/null
+++ b/ACE/examples/Reactor/Misc/test_event_handler_t.cpp
@@ -0,0 +1,47 @@
+// $Id$
+
+#include "ace/Event_Handler_T.h"
+#include "ace/Log_Msg.h"
+
+ACE_RCSID(Misc, test_event_handler_t, "$Id$")
+
+#if defined (ACE_HAS_TEMPLATE_TYPEDEFS)
+
+class ACE_Test_Sig_Handler
+{
+public:
+ ACE_Test_Sig_Handler (void) {}
+ virtual ~ACE_Test_Sig_Handler (void) {}
+ virtual ACE_HANDLE get_handle (void) const { return 0; }
+ virtual void set_handle (ACE_HANDLE) {}
+ virtual int handle_async_io (ACE_HANDLE) { return 0; }
+ virtual int shutdown (ACE_HANDLE, ACE_Reactor_Mask) { return 0; }
+ virtual int signal_handler (int /* signum */,
+ siginfo_t * = 0,
+ ucontext_t * = 0)
+ {
+ return 0;
+ }
+};
+
+int
+ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ typedef ACE_Event_Handler_T<ACE_Test_Sig_Handler> EH_SH;
+
+ // Tie the ACE_Event_Handler_T together with the methods from ACE_Test_Sig_Handler.
+ EH_SH tied_sh (new ACE_Test_Sig_Handler, 1,
+ &ACE_Test_Sig_Handler::get_handle,
+ &ACE_Test_Sig_Handler::handle_async_io,
+ &ACE_Test_Sig_Handler::shutdown,
+ &ACE_Test_Sig_Handler::signal_handler);
+ return 0;
+}
+
+#else
+int
+ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ ACE_ERROR_RETURN ((LM_ERROR, "your platform does not support template typedefs\n"), 1);
+}
+#endif /* ACE_HAS_TEMPLATE_TYPEDEFS */
diff --git a/ACE/examples/Reactor/Misc/test_reactors.cpp b/ACE/examples/Reactor/Misc/test_reactors.cpp
new file mode 100644
index 00000000000..a08580672e0
--- /dev/null
+++ b/ACE/examples/Reactor/Misc/test_reactors.cpp
@@ -0,0 +1,195 @@
+// $Id$
+
+// Perform a torture test of multiple ACE_Reactors and ACE_Tasks in
+// the same process... Thanks to Detlef Becker for contributing this.
+
+#include "ace/Reactor.h"
+#include "ace/Service_Config.h"
+#include "ace/Task.h"
+#include "ace/Atomic_Op.h"
+
+ACE_RCSID(Misc, test_reactors, "$Id$")
+
+#if defined (ACE_HAS_THREADS)
+
+#include "ace/Recursive_Thread_Mutex.h"
+
+static const int NUM_INVOCATIONS = 10;
+static const int MAX_TASKS = 20;
+
+class Test_Task : public ACE_Task<ACE_MT_SYNCH>
+{
+public:
+ Test_Task (void);
+ ~Test_Task (void);
+
+ virtual int open (void *args = 0);
+ virtual int close (u_long flags = 0);
+ virtual int svc (void);
+
+ virtual int handle_input (ACE_HANDLE handle);
+ virtual int handle_close (ACE_HANDLE fd,
+ ACE_Reactor_Mask close_mask);
+
+private:
+ int handled_;
+
+ static int task_count_;
+};
+
+int Test_Task::task_count_ = 0;
+
+static ACE_Atomic_Op<ACE_Thread_Mutex, int> done_count = MAX_TASKS * 2;
+
+static ACE_Recursive_Thread_Mutex reclock_;
+
+Test_Task::Test_Task (void)
+ : handled_ (0)
+{
+ ACE_GUARD (ACE_Recursive_Thread_Mutex, ace_mon, reclock_);
+
+ Test_Task::task_count_++;
+ ACE_DEBUG ((LM_DEBUG,
+ "(%t) TT+ Test_Task::task_count_ = %d\n",
+ Test_Task::task_count_));
+}
+
+Test_Task::~Test_Task (void)
+{
+ ACE_GUARD (ACE_Recursive_Thread_Mutex, ace_mon, reclock_);
+
+ ACE_DEBUG ((LM_DEBUG,
+ "(%t) TT- Test_Task::task_count_ = %d\n",
+ Test_Task::task_count_));
+}
+
+int
+Test_Task::open (void *args)
+{
+ this->reactor ((ACE_Reactor *) args);
+ return this->activate (THR_NEW_LWP);
+}
+
+int
+Test_Task::close (u_long)
+{
+ ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex, ace_mon, reclock_, -1);
+
+ Test_Task::task_count_--;
+ ACE_DEBUG ((LM_DEBUG,
+ "(%t) close Test_Task::task_count_ = %d\n",
+ Test_Task::task_count_));
+ return 0;
+}
+
+int
+Test_Task::svc (void)
+{
+ for (int i = 0; i < NUM_INVOCATIONS; i++)
+ {
+ ACE_OS::thr_yield ();
+
+ // ACE_DEBUG ((LM_DEBUG, "(%t) calling notify %d\n", i));
+
+ if (this->reactor ()->notify (this, ACE_Event_Handler::READ_MASK) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, "(%t) %p\n", "notify"), -1);
+
+ // ACE_DEBUG ((LM_DEBUG, "(%t) leaving notify %d\n", i));
+ }
+
+ return 0;
+}
+
+int
+Test_Task::handle_close (ACE_HANDLE,
+ ACE_Reactor_Mask)
+{
+ ACE_DEBUG ((LM_DEBUG, "(%t) handle_close\n"));
+ return 0;
+}
+
+int
+Test_Task::handle_input (ACE_HANDLE)
+{
+ ACE_DEBUG ((LM_DEBUG, "(%t) handle_input\n"));
+
+ this->handled_++;
+
+ if (this->handled_ == NUM_INVOCATIONS)
+ {
+ done_count--;
+ ACE_DEBUG ((LM_DEBUG,
+ "(%t) handle_input, handled_ = %d, done_count = %d\n",
+ this->handled_, done_count.value ()));
+ }
+
+ ACE_OS::thr_yield ();
+ return -1;
+}
+
+static void *
+worker (void *args)
+{
+ ACE_Reactor *reactor = (ACE_Reactor *) args;
+
+ reactor->owner (ACE_Thread::self ());
+
+ ACE_Time_Value timeout (4);
+
+ for (;;)
+ {
+ //ACE_DEBUG ((LM_DEBUG, "(%t) calling handle_events\n"));
+
+ switch (reactor->handle_events (timeout))
+ {
+ case -1:
+ ACE_ERROR_RETURN ((LM_ERROR, "(%t) %p\n", "reactor"), 0);
+ /* NOTREACHED */
+ case 0:
+ ACE_ERROR_RETURN ((LM_ERROR, "(%t) timeout\n"), 0);
+ /* NOTREACHED */
+ }
+
+ // ACE_DEBUG ((LM_DEBUG, "(%t) done with handle_events\n"));
+
+ }
+
+ ACE_NOTREACHED(return 0);
+}
+
+int
+ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ ACE_Reactor *react1 = ACE_Reactor::instance ();
+ ACE_Reactor *react2 = new ACE_Reactor ();
+ Test_Task tt1[MAX_TASKS];
+ Test_Task tt2[MAX_TASKS];
+
+ for (int i = 0; i < MAX_TASKS; i++)
+ {
+ tt1[i].open (react1);
+ tt2[i].open (react2);
+ }
+
+ if (ACE_Thread_Manager::instance ()->spawn
+ (ACE_THR_FUNC (worker), (void *) react1, THR_NEW_LWP) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "spawn"), -1);
+
+ else if (ACE_Thread_Manager::instance ()->spawn
+ (ACE_THR_FUNC (worker), (void *) react2, THR_NEW_LWP) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "spawn"), -1);
+
+ ACE_Thread_Manager::instance ()->wait ();
+ ACE_DEBUG ((LM_DEBUG, "(%t) done\n"));
+
+ return 0;
+}
+
+#else
+int
+main (int, char *[])
+{
+ ACE_ERROR ((LM_ERROR, "threads not supported on this platform\n"));
+ return 0;
+}
+#endif /* ACE_HAS_THREADS */
diff --git a/ACE/examples/Reactor/Misc/test_signals_1.cpp b/ACE/examples/Reactor/Misc/test_signals_1.cpp
new file mode 100644
index 00000000000..b0410f572c1
--- /dev/null
+++ b/ACE/examples/Reactor/Misc/test_signals_1.cpp
@@ -0,0 +1,114 @@
+// $Id$
+
+// This simple program illustrates the difference between handling
+// signals via the Reactor (which doesn't cause the event loop to
+// terminate) and signals that aren't handled via the Reactor (which
+// do).
+
+#include "ace/Service_Config.h"
+#include "ace/Reactor.h"
+#include "ace/Log_Msg.h"
+#include "ace/Signal.h"
+
+ACE_RCSID(Misc, test_signals_1, "$Id$")
+
+// Number of times to allow signal to execute until we quit.
+static size_t count = 10;
+
+static void
+my_signal_function (int sig)
+{
+ ACE_DEBUG ((LM_DEBUG,
+ "Executed non-ACE signal handler for signal %S\n",
+ sig));
+}
+
+class My_Handler : public ACE_Event_Handler
+{
+public:
+ virtual int handle_signal (int sig,
+ siginfo_t *,
+ ucontext_t *)
+ {
+ // @@ Note that this code is not portable to all OS platforms
+ // since it uses print statements within signal handler context.
+ ACE_DEBUG ((LM_DEBUG,
+ "Executed ACE signal handler for signal %S, count = %d\n",
+ sig,
+ count));
+ count--;
+
+ if (count == 0)
+ ACE_Reactor::end_event_loop ();
+
+ return 0;
+ }
+
+ virtual int handle_timeout (const ACE_Time_Value &,
+ const void *arg)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ "%s\n",
+ (const char *) arg));
+ return 0;
+ }
+};
+
+int
+ACE_TMAIN (int argc, ACE_TCHAR *argv[])
+{
+ // First you need a handler for the timeout.
+ My_Handler my_handler;
+
+ // This is the timeout period in seconds.
+ ACE_Time_Value period (ACE_DEFAULT_TIMEOUT);
+
+ if (argc > 1)
+ period.set (ACE_OS::atoi (argv[1]), 0);
+
+ // Set up the periodic interval timer.
+ if (ACE_Reactor::instance ()->schedule_timer
+ (&my_handler,
+ "hello",
+ period,
+ period) == -1)
+ ACE_ERROR_RETURN ((LM_DEBUG,
+ "%p\n",
+ "schedule_timer"),
+ -1);
+
+ // Set up an ACE signal handler.
+
+ if (ACE_Reactor::instance ()->register_handler
+ (SIGINT,
+ &my_handler) == -1)
+ ACE_ERROR_RETURN ((LM_DEBUG,
+ "%p\n",
+ "register_handler"),
+ -1);
+
+ // Set up a non-ACE signal handler. When this goes off, the Reactor
+ // should return from its <run_event_loop> method.
+ ACE_Sig_Action sig ((ACE_SignalHandler) my_signal_function,
+ SIGQUIT);
+ ACE_UNUSED_ARG (sig);
+
+ ACE_DEBUG ((LM_DEBUG,
+ "starting event loop that runs until you've typed ^C a total of 10 times or ^\\ once.\n"));
+
+ // This call executes the reactor events until we're finished.
+ int result = ACE_Reactor::run_event_loop ();
+
+ ACE_DEBUG ((LM_DEBUG,
+ "result = %d\n",
+ result));
+
+ // Make sure to remove my_handler before exiting main() since
+ // otherwise weird things can happen...
+ if (ACE_Reactor::instance ()->cancel_timer (&my_handler) == -1)
+ ACE_ERROR_RETURN ((LM_DEBUG,
+ "%p\n",
+ "cancel_timer"),
+ -1);
+ return 0;
+}
diff --git a/ACE/examples/Reactor/Misc/test_signals_2.cpp b/ACE/examples/Reactor/Misc/test_signals_2.cpp
new file mode 100644
index 00000000000..466ab58482f
--- /dev/null
+++ b/ACE/examples/Reactor/Misc/test_signals_2.cpp
@@ -0,0 +1,291 @@
+// $Id$
+
+// Test the ability of the Reactor/Signal_Handler to register multiple
+// handler per-signal.
+
+/* This test works as follows:
+
+ 1. To test the "original" semantics of ACE (i.e., only one
+ ACE_Event_Handler can be registered per signal), you don't
+ need to do anything special. Existing programs work the
+ same since giving the Reactor's constructor a 0 value
+ (which is the default argument, BTW) instructs it to behave
+ as before. When a 0 is given, the ACE_Reactor's
+ constructor/open method creates an instance of
+ ACE_Sig_Handler and assigns this to an internal pointer.
+ This pointer is then used to dispatch all signal-related
+ methods within the Reactor. The default ACE_Sig_Handler
+ only allows *one* ACE_Event_Handler to be registered
+ per-signal.
+
+ To run this version of the test do the following:
+
+ % ./test-signal
+ ./test_signals
+ waiting for SIGINT or SIGQUIT
+ ^C
+ signal Interrupt occurred in Sig_Handler_2 (fruity, 0, 0) with count = 1
+ waiting for SIGINT or SIGQUIT
+ ^\
+ signal Quit occurred in Sig_Handler_2 (fruity, 0, 0) with count = 2
+ shutting down SIGQUIT in Sig_Handler_2 (fruity, 0, 0)
+ waiting for SIGINT or SIGQUIT
+ ^C
+ signal Interrupt occurred in Sig_Handler_2 (fruity, 0, 0) with count = 3
+ waiting for SIGINT or SIGQUIT
+ ^\Quit (core dumped)
+
+ Note that in this test only one handler (the last one --
+ "Sig_Handler_2 (fruity)") is actually registered. BTW, the
+ core dump is the expected behavior since the default
+ disposition is restored when there are no more handlers
+ (see the code below).
+
+ 2. To test the "multiple handlers per-signal semantics", you
+ need to pass the constructor/open method of the ACE_Reactor
+ a pointer to a an instance of ACE_Sig_Handlers (note the
+ plural "s"). ACE_Sig_Handlers is a class that derives from
+ ACE_Sig_Handler. The difference between these two classes
+ is that (1) ACE_Sig_Handlers::register_signal allows
+ multiple ACE_Event_Handlers to be registered per-signal and
+ (2) it enables SA_RESTART by default. This class also
+ implements Detlef Becker's algorithm for integrating ACE
+ signal handling with 3rd party libraries.
+
+ To run this version of the test do the following:
+
+ % ./test_signals 1
+
+ waiting for SIGINT or SIGQUIT
+ ^C
+ signal Interrupt occurred in external handler!
+ signal Interrupt occurred in Sig_Handler_1 (howdy, 3, 1) with count = 1
+ shutting down SIGINT in Sig_Handler_1 (howdy, 3, 1)
+ signal Interrupt occurred in Sig_Handler_1 (doody, 5, 4) with count = 1
+ shutting down SIGINT in Sig_Handler_1 (doody, 5, 4)
+ signal Interrupt occurred in Sig_Handler_2 (tutty, 7, 6) with count = 1
+ signal Interrupt occurred in Sig_Handler_2 (fruity, 9, 8) with count = 1
+ waiting for SIGINT or SIGQUIT
+ ^\
+ signal Quit occurred in Sig_Handler_1 (howdy, 3, 1) with count = 2
+ shutting down SIGQUIT in Sig_Handler_1 (howdy, 3, 1)
+ signal Quit occurred in Sig_Handler_1 (doody, 5, 4) with count = 2
+ shutting down SIGQUIT in Sig_Handler_1 (doody, 5, 4)
+ signal Quit occurred in Sig_Handler_2 (tutty, 7, 6) with count = 2
+ shutting down SIGQUIT in Sig_Handler_2 (tutty, 7, 6)
+ signal Quit occurred in Sig_Handler_2 (fruity, 9, 8) with count = 2
+ shutting down SIGQUIT in Sig_Handler_2 (fruity, 9, 8)
+ waiting for SIGINT or SIGQUIT
+ ^C
+ signal Interrupt occurred in external handler!
+ signal Interrupt occurred in Sig_Handler_2 (tutty, 7, 6) with count = 3
+ signal Interrupt occurred in Sig_Handler_2 (fruity, 9, 8) with count = 3
+ waiting for SIGINT or SIGQUIT
+ ^\Quit (core dumped)
+
+ When this test begins all four handlers are registered and
+ dispatched when a SIGINT or SIGQUIT occurs. After the
+ first SIGINT, the handle_signal method of the Sig_Handler_1
+ objects unregister themselves. At that point there are 4
+ SIGQUIT handlers left, but only 2 of our SIGINT handlers
+ left (and the 1 external handler). After the first
+ SIGQUIT, there are no SIGQUIT handlers left since they all
+ deregister themselves (which restores the "SIG_DFL"
+ disposition). On the second SIGINT there are only 3
+ handlers left (2 of ours and 1 external). Finally, on the
+ second SIGQUIT we exit and dump core since that's what
+ happens with the default disposition for SIGQUIT. */
+
+
+#include "ace/Reactor.h"
+#include "ace/WFMO_Reactor.h"
+#include "ace/Select_Reactor.h"
+#include "ace/Log_Msg.h"
+#include "ace/Signal.h"
+
+ACE_RCSID(Misc, test_signals_2, "$Id$")
+
+class Sig_Handler_1 : public ACE_Event_Handler
+{
+public:
+ Sig_Handler_1 (ACE_Reactor &reactor, const char *msg)
+ : msg_ (msg),
+ count_ (0),
+ reactor_ (reactor)
+ {
+ // Register the signal handlers.
+ this->quit_sigkey_ =
+ reactor.register_handler (SIGQUIT, this);
+ this->int_sigkey_ =
+ reactor.register_handler (SIGINT, this);
+
+ if (this->quit_sigkey_ == -1 || this->int_sigkey_ == -1)
+ ACE_ERROR ((LM_ERROR,
+ "%p\n",
+ "register_handler"));
+ }
+
+ // @@ Note that this code is not portable to all OS platforms since
+ // it does print statements within the signal handler.
+ virtual int handle_signal (int signum,
+ siginfo_t *,
+ ucontext_t *)
+ {
+ this->count_++;
+ ACE_DEBUG ((LM_DEBUG,
+ "\nsignal %S occurred in Sig_Handler_1 (%s, %d, %d) with count = %d",
+ signum,
+ this->msg_,
+ this->int_sigkey_,
+ this->quit_sigkey_,
+ this->count_));
+
+ if (this->count_ != 1 && signum == SIGQUIT)
+ {
+ if (this->reactor_.remove_handler (SIGQUIT,
+ 0,
+ 0,
+ this->quit_sigkey_) == -1)
+ ACE_ERROR ((LM_ERROR,
+ "\n%p",
+ "remove_handler"));
+ else
+ ACE_DEBUG ((LM_DEBUG,
+ "\nshutting down SIGQUIT in Sig_Handler_1 (%s, %d, %d)",
+ this->msg_,
+ this->int_sigkey_,
+ this->quit_sigkey_));
+ }
+ else if (this->count_ != 2 && signum == SIGINT)
+ {
+ if (this->reactor_.remove_handler (SIGINT,
+ 0,
+ 0,
+ this->int_sigkey_) == -1)
+ ACE_ERROR ((LM_ERROR,
+ "\n%p",
+ "remove_handler"));
+ else
+ ACE_DEBUG ((LM_DEBUG,
+ "\nshutting down SIGINT in Sig_Handler_1 (%s, %d, %d)",
+ this->msg_,
+ this->int_sigkey_,
+ this->quit_sigkey_));
+ }
+ return 0;
+ }
+
+protected:
+ const char *msg_;
+ int count_;
+ int int_sigkey_;
+ int quit_sigkey_;
+ ACE_Reactor &reactor_;
+};
+
+class Sig_Handler_2 : public Sig_Handler_1
+{
+public:
+ Sig_Handler_2 (ACE_Reactor &reactor, const char *msg)
+ : Sig_Handler_1 (reactor, msg)
+ {
+ }
+
+ virtual int handle_signal (int signum,
+ siginfo_t *,
+ ucontext_t *)
+ {
+ this->count_++;
+ ACE_DEBUG ((LM_DEBUG,
+ "\nsignal %S occurred in Sig_Handler_2 (%s, %d, %d) with count = %d",
+ signum,
+ this->msg_,
+ this->int_sigkey_,
+ this->quit_sigkey_,
+ this->count_));
+ if (this->count_ != 0 && signum == SIGQUIT)
+ {
+ if (this->reactor_.remove_handler (SIGQUIT, 0, 0,
+ this->quit_sigkey_) == -1)
+ ACE_ERROR ((LM_ERROR,
+ "\n%p",
+ "remove_handler"));
+ else
+ ACE_DEBUG ((LM_DEBUG,
+ "\nshutting down SIGQUIT in Sig_Handler_2 (%s, %d, %d)",
+ this->msg_,
+ this->int_sigkey_,
+ this->quit_sigkey_));
+ }
+ return 0;
+ }
+};
+
+static void
+external_handler (int signum)
+{
+ ACE_DEBUG ((LM_DEBUG,
+ "\nsignal %S occurred in external handler!",
+ signum));
+}
+
+#if !defined (HPUX)
+int
+ACE_TMAIN (int argc, ACE_TCHAR *[])
+{
+ // If argc > 1 then allow multiple handlers per-signal, else just
+ // allow 1 handler per-signal.
+ ACE_Sig_Handlers multi_handlers;
+
+#if defined (ACE_WIN32)
+ ACE_WFMO_Reactor reactor_impl (argc > 1
+ ? &multi_handlers
+ : (ACE_Sig_Handler *) 0);
+#else
+ ACE_Select_Reactor reactor_impl (argc > 1
+ ? &multi_handlers
+ : (ACE_Sig_Handler *) 0);
+#endif /* ACE_WIN32 */
+ ACE_Reactor reactor (&reactor_impl);
+
+ if (argc > 1)
+ {
+ // Register an "external" signal handler so that the
+ // ACE_Sig_Handlers code will have something to incorporate!
+
+ ACE_SignalHandler eh = (ACE_SignalHandler) external_handler;
+ ACE_Sig_Action sa (eh);
+
+ sa.register_action (SIGINT);
+ }
+
+ // Create a bevy of handlers.
+ Sig_Handler_1 h1 (reactor, "howdy");
+ Sig_Handler_1 h2 (reactor, "doody");
+ Sig_Handler_2 h3 (reactor, "tutty");
+ Sig_Handler_2 h4 (reactor, "fruity");
+
+ // Wait for user to type SIGINT and SIGQUIT.
+
+ for (;;)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ "\nwaiting for SIGINT or SIGQUIT\n"));
+
+ if (reactor.handle_events () == -1)
+ ACE_ERROR ((LM_ERROR,
+ "%p\n",
+ "handle_events"));
+ }
+
+ ACE_NOTREACHED (return 0);
+}
+#else
+int
+main (int, char *[])
+{
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "The HP C++ compiler is too lame to support this feature\n"),
+ -1);
+}
+#endif /* HPUX */
diff --git a/ACE/examples/Reactor/Misc/test_time_value.cpp b/ACE/examples/Reactor/Misc/test_time_value.cpp
new file mode 100644
index 00000000000..a1c1c874b78
--- /dev/null
+++ b/ACE/examples/Reactor/Misc/test_time_value.cpp
@@ -0,0 +1,83 @@
+// $Id$
+
+// FUZZ: disable check_for_streams_include
+#include "ace/streams.h"
+
+#include "ace/Log_Msg.h"
+#include "ace/Time_Value.h"
+
+ACE_RCSID(Misc, test_time_value, "$Id$")
+
+inline int my_abs (int d) { return d > 0 ? d : -d; }
+
+ostream &
+operator<< (ostream &stream, const ACE_Time_Value &tv)
+{
+ if (tv.usec () < 0 || tv.sec () < 0)
+ stream << "-";
+
+ stream << my_abs (int (tv.sec ())) << "."
+// << setw (6) << setfill ('0')
+ << my_abs (int (tv.usec ()));
+ return stream;
+}
+
+int
+main (int, char *[])
+{
+ ACE_Time_Value tv1;
+ ACE_Time_Value tv2 (2);
+ ACE_Time_Value tv3 (100);
+ ACE_Time_Value tv4 (1, 1000000);
+ ACE_Time_Value tv5 (2);
+ ACE_Time_Value tv6 (1, -1000000);
+
+ ACE_ASSERT (tv1 == ACE_Time_Value (0));
+ ACE_ASSERT (tv2 < tv3);
+ ACE_ASSERT (tv2 <= tv2);
+ ACE_ASSERT (tv2 >= tv4);
+ ACE_ASSERT (tv5 >= tv6);
+ ACE_ASSERT (tv2 == ACE_Time_Value (1, 1000000));
+ ACE_ASSERT (tv5 == tv4);
+ ACE_ASSERT (tv2 == tv4);
+ ACE_ASSERT (tv1 != tv2);
+ ACE_ASSERT (tv6 == tv1);
+
+# if defined (ACE_NDEBUG)
+ ACE_UNUSED_ARG (tv1);
+ ACE_UNUSED_ARG (tv2);
+ ACE_UNUSED_ARG (tv3);
+ ACE_UNUSED_ARG (tv4);
+ ACE_UNUSED_ARG (tv5);
+ ACE_UNUSED_ARG (tv6);
+# endif /* ACE_NDEBUG */
+
+ cout << "0,0 :\t\t" << ACE_Time_Value (0,0) << endl;
+ cout << "-0,0 :\t\t" << ACE_Time_Value (-0,0) << endl;
+ cout << "0,-0 :\t\t" << ACE_Time_Value (0,-0) << endl;
+ cout << "-0,-0 :\t\t" << ACE_Time_Value (-0,-0) << endl;
+ cout << endl;
+
+ cout << "0,1 :\t\t" << ACE_Time_Value (0,1) << endl;
+ cout << "1,0 :\t\t" << ACE_Time_Value (1,0) << endl;
+ cout << "-1,0 :\t\t" << ACE_Time_Value (-1,0) << endl;
+ cout << "-1,-0 :\t\t" << ACE_Time_Value (-1,-0) << endl;
+ cout << endl;
+
+ cout << "1,1 :\t\t" << ACE_Time_Value (1,1) << endl;
+ cout << "-1,1 :\t\t" << ACE_Time_Value (-1,1) << endl;
+ cout << "1,-1 :\t\t" << ACE_Time_Value (1,-1) << endl;
+ cout << "-1,-1 :\t\t" << ACE_Time_Value (-1,-1) << endl;
+ cout << endl;
+
+ cout << "1,-1111111 :\t" << ACE_Time_Value (1,-1111111) << endl;
+ cout << "1,-100000 :\t" << ACE_Time_Value (1,-100000) << endl;
+ cout << "1,-1000000 :\t" << ACE_Time_Value (1,-1000000) << endl;
+ cout << "-1,1000000 :\t" << ACE_Time_Value (-1,1000000) << endl;
+ cout << "5,-1000000 :\t" << ACE_Time_Value (5,-1000000) << endl;
+ cout << "5,-1500000 :\t" << ACE_Time_Value (5,-1500000) << endl;
+ cout << "2,-2500000 :\t" << ACE_Time_Value (2,-2500000) << endl;
+ cout << "2,-4500000 :\t" << ACE_Time_Value (2,-4500000) << endl;
+
+ return 0;
+}
diff --git a/ACE/examples/Reactor/Misc/test_timer_queue.cpp b/ACE/examples/Reactor/Misc/test_timer_queue.cpp
new file mode 100644
index 00000000000..64138e13daf
--- /dev/null
+++ b/ACE/examples/Reactor/Misc/test_timer_queue.cpp
@@ -0,0 +1,115 @@
+// $Id$
+
+#include "ace/OS_NS_sys_time.h"
+#include "ace/Timer_Heap.h"
+#include "ace/Timer_List.h"
+#include "ace/Timer_Queue.h"
+#include "ace/Log_Msg.h"
+#include "ace/Recursive_Thread_Mutex.h"
+#include "ace/Null_Mutex.h"
+
+ACE_RCSID(Misc, test_timer_queue, "$Id$")
+
+class Example_Handler : public ACE_Event_Handler
+{
+public:
+ Example_Handler (void)
+ : count_ (1)
+ {}
+
+ virtual int handle_timeout (const ACE_Time_Value &, const void *arg)
+ {
+ int *times = (int *) arg;
+
+ ACE_DEBUG ((LM_DEBUG,
+ "yow, the time has come and gone %d times %d, Horatio!\n",
+ this->count_++,
+ *times));
+ delete times;
+ return 0;
+ }
+
+private:
+ int count_;
+};
+
+static void
+test_functionality (ACE_Timer_Queue *tq)
+{
+ Example_Handler eh;
+
+ ACE_ASSERT (tq->is_empty ());
+ ACE_ASSERT (ACE_Time_Value::zero == ACE_Time_Value (0));
+ const void *timer_act = 0;
+
+ ACE_NEW (timer_act, int (1));
+ long timer_id1 = tq->schedule (&eh, timer_act, ACE_OS::gettimeofday ());
+
+ // Use timer_id outside of an assert, so that we don't get compile
+ // warnings with ACE_NDEBUG about it being unused.
+ if (timer_id1 == -1)
+ ACE_ERROR ((LM_ERROR, "%p\n", "schedule () failed"));
+ ACE_ASSERT (timer_id1 != -1);
+
+ ACE_NEW (timer_act, int (42));
+ long result = tq->schedule (&eh, timer_act, ACE_OS::gettimeofday ());
+ ACE_ASSERT (result != -1);
+ ACE_NEW (timer_act, int (42));
+ result = tq->schedule (&eh, timer_act, ACE_OS::gettimeofday ());
+ ACE_ASSERT (result != -1);
+
+ result = tq->cancel (timer_id1, &timer_act);
+ ACE_ASSERT (result == 1);
+ delete (int *) timer_act;
+ result = tq->is_empty ();
+ ACE_ASSERT (!result);
+
+ result = tq->expire ();
+ ACE_ASSERT (result == 2);
+
+ ACE_NEW (timer_act, int (4));
+ timer_id1 = tq->schedule (&eh, timer_act, ACE_OS::gettimeofday ());
+ ACE_ASSERT (timer_id1 != -1);
+ ACE_NEW (timer_act, int (5));
+ long timer_id2 = tq->schedule (&eh, timer_act, ACE_OS::gettimeofday ());
+ ACE_ASSERT (timer_id2 != -1);
+
+ result = tq->cancel (timer_id1, &timer_act);
+ ACE_ASSERT (result == 1);
+ delete (int *) timer_act;
+ result = tq->cancel (timer_id2, &timer_act);
+ ACE_ASSERT (result == 1);
+ delete (int *) timer_act;
+ result = tq->is_empty ();
+ ACE_ASSERT (result == 1);
+ result = tq->expire ();
+ ACE_ASSERT (result == 0);
+}
+
+struct Timer_Queues
+{
+ ACE_Timer_Queue *queue_;
+ // Pointer to the subclass of <ACE_Timer_Queue> that we're testing.
+
+ const char *name_;
+ // Name of the Queue that we're testing.
+};
+
+static Timer_Queues timer_queues[] =
+{
+ { new ACE_Timer_List, "ACE_Timer_List" },
+ { new ACE_Timer_Heap, "ACE_Timer_Heap" },
+ { 0, 0 },
+};
+
+int
+ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ for (int i = 0; timer_queues[i].name_ != 0; i++)
+ {
+ test_functionality (timer_queues[i].queue_);
+ delete timer_queues[i].queue_;
+ }
+
+ return 0;
+}
diff --git a/ACE/examples/Reactor/Multicast/.cvsignore b/ACE/examples/Reactor/Multicast/.cvsignore
new file mode 100644
index 00000000000..955ffdc75d5
--- /dev/null
+++ b/ACE/examples/Reactor/Multicast/.cvsignore
@@ -0,0 +1,4 @@
+client
+client
+server
+server
diff --git a/ACE/examples/Reactor/Multicast/Log_Wrapper.cpp b/ACE/examples/Reactor/Multicast/Log_Wrapper.cpp
new file mode 100644
index 00000000000..055b57b9975
--- /dev/null
+++ b/ACE/examples/Reactor/Multicast/Log_Wrapper.cpp
@@ -0,0 +1,81 @@
+// $Id$
+
+// client.C
+
+#include "Log_Wrapper.h"
+#include "ace/OS_NS_unistd.h"
+#include "ace/OS_NS_sys_utsname.h"
+#include "ace/OS_NS_string.h"
+#include "ace/OS_NS_netdb.h"
+
+ACE_RCSID(Multicast, Log_Wrapper, "$Id$")
+
+Log_Wrapper::Log_Wrapper (void)
+{
+ sequence_number_ = 0;
+ this->log_msg_.app_id = ACE_OS::getpid ();
+}
+
+Log_Wrapper::~Log_Wrapper (void)
+{
+}
+
+// Set the log_msg_ host address.
+
+int
+Log_Wrapper::open (const int port, const char *mcast_addr)
+{
+ struct hostent *host_info;
+ ACE_utsname host_data;
+
+ if (ACE_OS::uname (&host_data) < 0)
+ return -1;
+
+#if defined (ACE_LACKS_UTSNAME_T)
+ if ((host_info = ACE_OS::gethostbyname
+ (ACE_TEXT_ALWAYS_CHAR(host_data.nodename))) == NULL)
+#else
+ if ((host_info = ACE_OS::gethostbyname (host_data.nodename)) == NULL)
+#endif
+ return -1;
+ else
+ ACE_OS::memcpy ((char *) &this->log_msg_.host,
+ (char *) host_info->h_addr,
+ host_info->h_length);
+
+ // This starts out initialized to all zeros!
+ server_ = ACE_INET_Addr (port, mcast_addr);
+
+ if (logger_.subscribe (server_) == -1)
+ perror("can't subscribe to multicast group"), exit(1);
+
+ // success.
+ return 0;
+}
+
+// Send the message to a logger object.
+// This wrapper fills in all the log_record info for you.
+// uses iovector stuff to make contiguous header and message.
+
+int
+Log_Wrapper::log_message (Log_Priority type, char *message)
+{
+ sequence_number_++;
+
+ this->log_msg_.type = type;
+ this->log_msg_.time = time (0);
+ this->log_msg_.msg_length = ACE_OS::strlen(message)+1;
+ this->log_msg_.sequence_number = htonl(sequence_number_);
+
+ iovec iovp[2];
+ iovp[0].iov_base = reinterpret_cast<char*> (&log_msg_);
+ iovp[0].iov_len = sizeof (log_msg_);
+ iovp[1].iov_base = message;
+ iovp[1].iov_len = log_msg_.msg_length;
+
+ logger_.send (iovp, 2);
+
+ // success.
+ return 0;
+}
+
diff --git a/ACE/examples/Reactor/Multicast/Log_Wrapper.h b/ACE/examples/Reactor/Multicast/Log_Wrapper.h
new file mode 100644
index 00000000000..10458f706bc
--- /dev/null
+++ b/ACE/examples/Reactor/Multicast/Log_Wrapper.h
@@ -0,0 +1,68 @@
+/* -*- C++ -*- */
+// $Id$
+
+// log_wrapper.h
+
+#include "ace/Profile_Timer.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/INET_Addr.h"
+#include "ace/SOCK_Dgram_Mcast.h"
+
+#ifndef _LOG_WRAPPER_H
+#define _LOG_WRAPPER_H
+
+class Log_Wrapper
+ // = TITLE
+ // Provide a wrapper around sending log messages via IP
+ // multicast.
+{
+public:
+ Log_Wrapper (void);
+ ~Log_Wrapper (void);
+
+ // = Types of logging messages.
+ enum Log_Priority
+ {
+ LM_MESSAGE,
+ LM_DEBUG,
+ LM_WARNING,
+ LM_ERROR,
+ LM_EMERG
+ };
+
+ int open (const int port, const char* mcast_addr);
+ // Subscribe to a given UDP multicast group
+
+ int log_message (Log_Priority type, char *message);
+ // send a string to the logger
+
+ // = Format of the logging record.
+ struct Log_Record
+ {
+ u_long sequence_number;
+ Log_Priority type;
+ long host;
+ long time;
+ long app_id;
+ long msg_length;
+ };
+
+private:
+ ACE_INET_Addr server_;
+ // Server address where records are logged.
+
+ u_long sequence_number_;
+ // Keep track of the sequence.
+
+ Log_Record log_msg_;
+ // One record used for many log messages.
+
+ ACE_SOCK_Dgram_Mcast logger_;
+ // A logger object.
+};
+
+#endif /* _LOG_WRAPPER_H */
diff --git a/ACE/examples/Reactor/Multicast/Makefile.am b/ACE/examples/Reactor/Multicast/Makefile.am
new file mode 100644
index 00000000000..60d65e7ebe8
--- /dev/null
+++ b/ACE/examples/Reactor/Multicast/Makefile.am
@@ -0,0 +1,50 @@
+## Process this file with automake to create Makefile.in
+##
+## $Id$
+##
+## This file was generated by MPC. Any changes made directly to
+## this file will be lost the next time it is generated.
+##
+## MPC Command:
+## /acebuilds/ACE_wrappers-repository/bin/mwc.pl -include /acebuilds/MPC/config -include /acebuilds/MPC/templates -feature_file /acebuilds/ACE_wrappers-repository/local.features -noreldefs -type automake -exclude build,Kokyu
+
+ACE_BUILDDIR = $(top_builddir)
+ACE_ROOT = $(top_srcdir)
+
+## Makefile.Reactor_Multicast_Client.am
+noinst_PROGRAMS = client
+
+client_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+client_SOURCES = \
+ Log_Wrapper.cpp \
+ client.cpp \
+ Log_Wrapper.h
+
+client_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Makefile.Reactor_Multicast_Server.am
+noinst_PROGRAMS += server
+
+server_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+server_SOURCES = \
+ Log_Wrapper.cpp \
+ server.cpp \
+ Log_Wrapper.h
+
+server_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Clean up template repositories, etc.
+clean-local:
+ -rm -f *~ *.bak *.rpo *.sym lib*.*_pure_* core core.*
+ -rm -f gcctemp.c gcctemp so_locations *.ics
+ -rm -rf cxx_repository ptrepository ti_files
+ -rm -rf templateregistry ir.out
+ -rm -rf ptrepository SunWS_cache Templates.DB
diff --git a/ACE/examples/Reactor/Multicast/README b/ACE/examples/Reactor/Multicast/README
new file mode 100644
index 00000000000..85f64cc8120
--- /dev/null
+++ b/ACE/examples/Reactor/Multicast/README
@@ -0,0 +1,15 @@
+The following test illustrates the SOCK Mcast multicast wrappers in
+conjunction with the Reactor. This test was written by Tim Harrison
+(harrison@cs.wustl.edu).
+
+To run the server type:
+
+% server &
+
+It will wait for the first message sent to it and then read for 5 seconds.
+
+To run the client type any of these:
+
+% client -m max_message_size -i iterations
+% client < <filename>
+% client
diff --git a/ACE/examples/Reactor/Multicast/Reactor_Multicast.mpc b/ACE/examples/Reactor/Multicast/Reactor_Multicast.mpc
new file mode 100644
index 00000000000..a15c53340e4
--- /dev/null
+++ b/ACE/examples/Reactor/Multicast/Reactor_Multicast.mpc
@@ -0,0 +1,17 @@
+// -*- MPC -*-
+// $Id$
+
+project(*client) : aceexe {
+ exename = client
+ Source_Files {
+ client.cpp
+ Log_Wrapper.cpp
+ }
+}
+project(*server) : aceexe {
+ exename = server
+ Source_Files {
+ server.cpp
+ Log_Wrapper.cpp
+ }
+}
diff --git a/ACE/examples/Reactor/Multicast/client.cpp b/ACE/examples/Reactor/Multicast/client.cpp
new file mode 100644
index 00000000000..25b18c2ae6c
--- /dev/null
+++ b/ACE/examples/Reactor/Multicast/client.cpp
@@ -0,0 +1,126 @@
+// $Id$
+
+// This program reads in messages from stdin and sends them to a
+// Log_Wrapper.
+
+#include "ace/OS_main.h"
+#include "ace/OS_NS_stdlib.h"
+#include "ace/OS_NS_string.h"
+#include "ace/OS_NS_unistd.h"
+#include "ace/OS_Memory.h"
+#include "ace/Get_Opt.h"
+#include "ace/Log_Msg.h"
+#include "Log_Wrapper.h"
+
+ACE_RCSID(Multicast, client, "$Id$")
+
+// Multi-cast address.
+static const char *MCAST_ADDR = ACE_DEFAULT_MULTICAST_ADDR;
+
+// UDP port.
+static const int UDP_PORT = ACE_DEFAULT_MULTICAST_PORT;
+
+// Maximum message size.
+static int max_message_size = BUFSIZ;
+
+// Number of times to send message of max_message_size.
+static int iterations = 0;
+
+static void
+parse_args (int argc, ACE_TCHAR *argv[])
+{
+ ACE_LOG_MSG->open (argv[0]);
+
+ // Start at argv[1]
+ ACE_Get_Opt getopt (argc, argv, ACE_TEXT("m:ui:"), 1);
+
+ for (int c; (c = getopt ()) != -1; )
+ switch (c)
+ {
+ case 'm':
+ max_message_size = ACE_OS::atoi (getopt.opt_arg ()) * BUFSIZ;
+ break;
+ case 'i':
+ iterations = ACE_OS::atoi (getopt.opt_arg ());
+ break;
+ case 'u':
+ // usage fallthrough
+ default:
+ ACE_ERROR ((LM_ERROR,
+ "%n: -m max_message_size (in k) -i iterations\n%a",
+ 1));
+ /* NOTREACHED */
+ }
+}
+
+int
+ACE_TMAIN (int argc, ACE_TCHAR **argv)
+{
+ int user_prompt;
+
+ parse_args (argc,argv);
+
+ ACE_DEBUG ((LM_DEBUG, "max buffer size = %d\n", max_message_size));
+
+ // Instantiate a log wrapper for logging
+ Log_Wrapper log;
+
+ // Make a connection to a logger.
+ if (log.open (UDP_PORT, MCAST_ADDR) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, "%p\n" "open"), -1);
+
+ char *buf;
+ ACE_NEW_RETURN (buf, char[max_message_size], -1);
+
+ // If -i has been specified, send max_message_size messages
+ // iterations number of times.
+ if (iterations)
+ {
+ ACE_OS::memset (buf, 1, max_message_size);
+
+ while (iterations--)
+ if (log.log_message (Log_Wrapper::LM_DEBUG, buf) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, "%p\n" "log"), -1);
+ }
+
+ // otherwise, a file has been redirected, or give prompts
+ else
+ {
+ // If a file has been redirected, don't activate user prompts.
+ if (ACE_OS::isatty (0))
+ user_prompt = 1;
+ else
+ user_prompt = 0;
+
+ // Continually read messages from stdin and log them.
+
+ for (int count = 1;;)
+ {
+ if (user_prompt)
+ ACE_DEBUG ((LM_DEBUG, "\nEnter message ('Q':quit):\n"));
+
+ ssize_t nbytes = ACE_OS::read (ACE_STDIN, buf, max_message_size);
+
+ if (nbytes <= 0)
+ break; // End of file or error.
+ buf[nbytes - 1] = '\0';
+
+ // Quitting?
+ if (user_prompt)
+ {
+ if (buf[0] == 'Q' || buf[0] == 'q')
+ break;
+ }
+ else // Keep from overrunning the receiver.
+ ACE_OS::sleep (1);
+
+ // Send the message to the logger.
+ if (log.log_message (Log_Wrapper::LM_DEBUG, buf) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, "%p\n" "log_message"), -1);
+ ACE_DEBUG ((LM_DEBUG, "finished sending message %d\n", count++));
+ }
+ }
+
+ ACE_DEBUG ((LM_DEBUG, "Client done.\n"));
+ return 0;
+}
diff --git a/ACE/examples/Reactor/Multicast/server.cpp b/ACE/examples/Reactor/Multicast/server.cpp
new file mode 100644
index 00000000000..65e39b97d1a
--- /dev/null
+++ b/ACE/examples/Reactor/Multicast/server.cpp
@@ -0,0 +1,247 @@
+// $Id$
+
+// server.cpp (written by Tim Harrison)
+
+// Listens to multicast address for client log messages. Prints
+// Mbits/sec received from client.
+
+#include "ace/OS_main.h"
+#include "ace/SOCK_Dgram.h"
+#include "ace/INET_Addr.h"
+#include "ace/SOCK_Dgram_Mcast.h"
+#include "ace/Reactor.h"
+#include "ace/Log_Msg.h"
+#include "Log_Wrapper.h"
+#include "ace/OS_NS_string.h"
+#include "ace/OS_NS_unistd.h"
+#include "ace/os_include/os_netdb.h"
+
+ACE_RCSID(Multicast, server, "$Id$")
+
+#if defined (ACE_HAS_IP_MULTICAST)
+class Server_Events : public ACE_Event_Handler
+{
+public:
+ Server_Events (u_short port,
+ const char *mcast_addr,
+ long time_interval = 0);
+ ~Server_Events (void);
+
+ virtual int handle_input (ACE_HANDLE fd);
+ virtual int handle_timeout (const ACE_Time_Value &tv,
+ const void *arg);
+
+ virtual ACE_HANDLE get_handle (void) const;
+
+ ACE_Time_Value *wait_time (void);
+
+private:
+ char *message_;
+ Log_Wrapper::Log_Record *log_record_;
+ char buf_[4 * BUFSIZ];
+ char hostname_[MAXHOSTNAMELEN];
+
+ int initialized_;
+ int count_;
+ long interval_;
+ // time interval to log messages
+
+ ACE_Time_Value *how_long_;
+ ACE_Reactor *reactor_;
+ ACE_SOCK_Dgram_Mcast mcast_dgram_;
+ ACE_INET_Addr remote_addr_;
+ ACE_INET_Addr mcast_addr_;
+
+ // = statistics on messages received
+ double total_bytes_received_;
+ int total_messages_received_;
+ int last_sequence_number_;
+};
+
+static const char MCAST_ADDR[] = ACE_DEFAULT_MULTICAST_ADDR;
+static const int UDP_PORT = ACE_DEFAULT_MULTICAST_PORT;
+static const int DURATION = 5;
+
+ACE_HANDLE
+Server_Events::get_handle (void) const
+{
+ return this->mcast_dgram_.get_handle ();
+}
+
+ACE_Time_Value *
+Server_Events::wait_time (void)
+{
+ return this->how_long_;
+}
+
+Server_Events::Server_Events (u_short port,
+ const char *mcast_addr,
+ long time_interval)
+ : initialized_ (0),
+ count_ (1),
+ interval_ (time_interval),
+ mcast_addr_ (port, mcast_addr),
+ total_bytes_received_ (0)
+{
+ // Use ACE_SOCK_Dgram_Mcast factory to subscribe to multicast group.
+
+ if (ACE_OS::hostname (this->hostname_,
+ MAXHOSTNAMELEN) == -1)
+ ACE_ERROR ((LM_ERROR,
+ "%p\n",
+ "hostname"));
+
+ else if (this->mcast_dgram_.subscribe (this->mcast_addr_) == -1)
+ ACE_ERROR ((LM_ERROR,
+ "%p\n",
+ "subscribe"));
+ else
+ {
+ // Point to NULL so that we block in the beginning.
+ this->how_long_ = 0;
+
+ this->log_record_ = (Log_Wrapper::Log_Record *) &buf_;
+ this->message_ = &buf_[sizeof (Log_Wrapper::Log_Record)];
+ }
+}
+
+// A destructor that emacs refuses to color blue ;-)
+
+Server_Events::~Server_Events (void)
+{
+ this->mcast_dgram_.unsubscribe ();
+
+ ACE_DEBUG ((LM_DEBUG,
+ "total bytes received = %d after %d second\n",
+ this->total_bytes_received_,
+ this->interval_));
+
+ ACE_DEBUG ((LM_DEBUG,
+ "Mbits/sec = %.2f\n",
+ (float) (total_bytes_received_ * 8 / (float) (1024*1024*interval_))));
+
+ ACE_DEBUG ((LM_DEBUG,
+ "last sequence number = %d\ntotal messages received = %d\ndiff = %d\n",
+ this->last_sequence_number_,
+ this->total_messages_received_,
+ this->last_sequence_number_ - total_messages_received_));
+}
+
+int
+Server_Events::handle_timeout (const ACE_Time_Value &,
+ const void *arg)
+{
+ ACE_DEBUG ((LM_DEBUG, "\t%d timeout%s occurred for %s.\n",
+ this->count_,
+ this->count_ == 1 ? "" : "s",
+ (char *) arg));
+
+ // Don't let the timeouts continue if there's no activity since
+ // otherwise we use up a lot of CPU time unnecessarily.
+ if (this->count_ == 5)
+ {
+ reactor ()->cancel_timer (this);
+ this->initialized_ = 0;
+
+ ACE_DEBUG ((LM_DEBUG,
+ "\tcancelled timeout for %s to avoid busy waiting.\n",
+ (char *) arg));
+ }
+
+ this->count_++;
+ return 0;
+}
+
+int
+Server_Events::handle_input (ACE_HANDLE)
+{
+ // Receive message from multicast group.
+ iovec iovp[2];
+ iovp[0].iov_base = buf_;
+ iovp[0].iov_len = sizeof (log_record_);
+ iovp[1].iov_base = &buf_[sizeof (log_record_)];
+ iovp[1].iov_len = 4 * BUFSIZ - sizeof (log_record_);
+
+ ssize_t retcode =
+ this->mcast_dgram_.recv (iovp,
+ 2,
+ this->remote_addr_);
+ if (retcode != -1)
+ {
+ total_messages_received_++;
+ total_bytes_received_ += retcode;
+ last_sequence_number_ =
+ ntohl (log_record_->sequence_number);
+
+ for (char *message_end = this->message_ + ACE_OS::strlen (this->message_) - 1;
+ ACE_OS::strchr ("\r\n \t", *message_end) != 0;
+ )
+ {
+ *message_end-- = '\0';
+ if (message_end == this->message_)
+ break;
+ }
+
+ ACE_DEBUG ((LM_DEBUG,
+ "sequence number = %d\n",
+ last_sequence_number_));
+ ACE_DEBUG ((LM_DEBUG,
+ "message = '%s'\n",
+ this->message_));
+
+ if (this->initialized_ == 0)
+ {
+ // Restart the timer since we've received events again.
+ if (reactor()->schedule_timer (this,
+ (void *) this->hostname_,
+ ACE_Time_Value::zero,
+ ACE_Time_Value (DURATION)) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%p\n",
+ "schedule_timer"),
+ -1);
+ this->initialized_ = 1;
+ }
+
+ this->count_ = 1;
+ return 0;
+ }
+ else
+ return -1;
+}
+
+int
+ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ // Instantiate a server which will receive messages for DURATION
+ // seconds.
+ Server_Events server_events (UDP_PORT,
+ MCAST_ADDR,
+ DURATION);
+ // Instance of the ACE_Reactor.
+ ACE_Reactor reactor;
+
+ if (reactor.register_handler (&server_events,
+ ACE_Event_Handler::READ_MASK) == -1)
+ ACE_ERROR ((LM_ERROR,
+ "%p\n%a",
+ "register_handler",
+ 1));
+
+ ACE_DEBUG ((LM_DEBUG,
+ "starting up server\n"));
+
+ for (;;)
+ reactor.handle_events (server_events.wait_time ());
+
+ ACE_NOTREACHED (return 0;)
+}
+#else
+int
+main (int, char *argv[])
+{
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "error: %s must be run on a platform that support IP multicast\n",
+ argv[0]), -1);
+}
+#endif /* ACE_HAS_IP_MULTICAST */
diff --git a/ACE/examples/Reactor/Ntalker/.cvsignore b/ACE/examples/Reactor/Ntalker/.cvsignore
new file mode 100644
index 00000000000..a9350d173bf
--- /dev/null
+++ b/ACE/examples/Reactor/Ntalker/.cvsignore
@@ -0,0 +1,2 @@
+ntalker
+ntalker
diff --git a/ACE/examples/Reactor/Ntalker/Makefile.am b/ACE/examples/Reactor/Ntalker/Makefile.am
new file mode 100644
index 00000000000..6efc3521a32
--- /dev/null
+++ b/ACE/examples/Reactor/Ntalker/Makefile.am
@@ -0,0 +1,33 @@
+## Process this file with automake to create Makefile.in
+##
+## $Id$
+##
+## This file was generated by MPC. Any changes made directly to
+## this file will be lost the next time it is generated.
+##
+## MPC Command:
+## /acebuilds/ACE_wrappers-repository/bin/mwc.pl -include /acebuilds/MPC/config -include /acebuilds/MPC/templates -feature_file /acebuilds/ACE_wrappers-repository/local.features -noreldefs -type automake -exclude build,Kokyu
+
+ACE_BUILDDIR = $(top_builddir)
+ACE_ROOT = $(top_srcdir)
+
+## Makefile.Reactor_Ntalker.am
+noinst_PROGRAMS = ntalker
+
+ntalker_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+ntalker_SOURCES = \
+ ntalker.cpp
+
+ntalker_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Clean up template repositories, etc.
+clean-local:
+ -rm -f *~ *.bak *.rpo *.sym lib*.*_pure_* core core.*
+ -rm -f gcctemp.c gcctemp so_locations *.ics
+ -rm -rf cxx_repository ptrepository ti_files
+ -rm -rf templateregistry ir.out
+ -rm -rf ptrepository SunWS_cache Templates.DB
diff --git a/ACE/examples/Reactor/Ntalker/README b/ACE/examples/Reactor/Ntalker/README
new file mode 100644
index 00000000000..191cef9256f
--- /dev/null
+++ b/ACE/examples/Reactor/Ntalker/README
@@ -0,0 +1,17 @@
+This test program illustrates how the ACE datagram multicast feature
+works. To run the test simply do the following on multiple machines:
+
+# Machine 1
+% ./ntalker
+
+# Machine 2
+% ./ntalker
+
+# Machine 3
+% ./ntalker
+
+Then, on one (or all) of the machines, type input into the keyboard.
+This input will be multicast to all the machines using IP multicast
+via the ACE_SOCK_Dgram_Mcast wrapper.
+
+When you want to shut down the sender, just type ^D.
diff --git a/ACE/examples/Reactor/Ntalker/Reactor_Ntalker.mpc b/ACE/examples/Reactor/Ntalker/Reactor_Ntalker.mpc
new file mode 100644
index 00000000000..ef2fb84d9a0
--- /dev/null
+++ b/ACE/examples/Reactor/Ntalker/Reactor_Ntalker.mpc
@@ -0,0 +1,6 @@
+// -*- MPC -*-
+// $Id$
+
+project : aceexe {
+ exename = ntalker
+}
diff --git a/ACE/examples/Reactor/Ntalker/ntalker.cpp b/ACE/examples/Reactor/Ntalker/ntalker.cpp
new file mode 100644
index 00000000000..80873ead1a9
--- /dev/null
+++ b/ACE/examples/Reactor/Ntalker/ntalker.cpp
@@ -0,0 +1,231 @@
+// $Id$
+
+// Listens to multicast address. After first message received, will
+// listen for 5 more seconds. Prints Mbits/sec received from client.
+
+#include "ace/OS_main.h"
+#include "ace/OS_NS_unistd.h"
+#include "ace/INET_Addr.h"
+#include "ace/SOCK_Dgram_Mcast.h"
+#include "ace/Reactor.h"
+#include "ace/Get_Opt.h"
+#include "ace/Thread_Manager.h"
+#include "ace/Service_Config.h"
+
+ACE_RCSID(Ntalker, ntalker, "$Id$")
+
+#if defined (ACE_HAS_IP_MULTICAST)
+// Network interface to subscribe to. This is hardware specific. use
+// netstat(1M) to find whether your interface is le0 or ie0
+
+static const ACE_TCHAR *INTERFACE = 0;
+static const char *MCAST_ADDR = ACE_DEFAULT_MULTICAST_ADDR;
+static const u_short UDP_PORT = ACE_DEFAULT_MULTICAST_PORT;
+
+class Handler : public ACE_Event_Handler
+{
+ // = TITLE
+ // Handle both multicast and stdin events.
+public:
+ // = Initialization and termination methods.
+ Handler (u_short udp_port,
+ const char *ip_addr,
+ const ACE_TCHAR *a_interface,
+ ACE_Reactor & );
+ // Constructor.
+
+ ~Handler (void);
+ // Destructor.
+
+ // Event demuxer hooks.
+ virtual int handle_input (ACE_HANDLE);
+ virtual int handle_close (ACE_HANDLE,
+ ACE_Reactor_Mask);
+ virtual ACE_HANDLE get_handle (void) const;
+
+private:
+ ACE_SOCK_Dgram_Mcast mcast_;
+ // Multicast wrapper.
+};
+
+ACE_HANDLE
+Handler::get_handle (void) const
+{
+ return this->mcast_.get_handle ();
+}
+
+int
+Handler::handle_input (ACE_HANDLE h)
+{
+ char buf[BUFSIZ];
+
+ if (h == ACE_STDIN)
+ {
+ ssize_t result = ACE_OS::read (h, buf, BUFSIZ);
+
+ if (result > 0)
+ {
+ if (this->mcast_.send (buf, result) != result)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%p\n",
+ "send error"),
+ -1);
+ return 0;
+ }
+ else if (result == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%p\n",
+ "can't read from STDIN"),
+ -1);
+ else // result == 0
+ {
+ ACE_Reactor::end_event_loop ();
+ return -1;
+ }
+ }
+ else
+ {
+ ACE_INET_Addr remote_addr;
+
+ // Receive message from multicast group.
+ ssize_t result = this->mcast_.recv (buf,
+ sizeof buf,
+ remote_addr);
+
+ if (result != -1)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ "received datagram from host %s on port %d bytes = %d\n",
+ remote_addr.get_host_name (),
+ remote_addr.get_port_number (),
+ result));
+ ACE_OS::write (ACE_STDERR, buf, result);
+ ACE_DEBUG ((LM_DEBUG,
+ "\n"));
+ return 0;
+ }
+
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%p\n",
+ "something amiss"),
+ -1);
+ }
+}
+
+int
+Handler::handle_close (ACE_HANDLE h, ACE_Reactor_Mask)
+{
+ if (h == ACE_STDIN)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ "STDIN_Events handle removed from reactor.\n"));
+ if (ACE_Reactor::instance ()->remove_handler
+ (this, ACE_Event_Handler::READ_MASK) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%p\n",
+ "remove_handler"),
+ -1);
+ }
+ else
+ ACE_DEBUG ((LM_DEBUG,
+ "Mcast_Events handle removed from reactor.\n"));
+ return 0;
+}
+
+Handler::~Handler (void)
+{
+ if (this->mcast_.unsubscribe () == -1)
+ ACE_ERROR ((LM_ERROR,
+ "%p\n",
+ "unsubscribe fails"));
+}
+
+Handler::Handler (u_short udp_port,
+ const char *ip_addr,
+ const ACE_TCHAR *a_interface,
+ ACE_Reactor &reactor)
+{
+ // Create multicast address to listen on.
+
+ ACE_INET_Addr sockmc_addr (udp_port, ip_addr);
+
+ // subscribe to multicast group.
+
+ if (this->mcast_.subscribe (sockmc_addr, 1, a_interface) == -1)
+ {
+ ACE_ERROR ((LM_ERROR,
+ "%p\n",
+ "can't subscribe to multicast group"));
+ }
+ // Disable loopbacks.
+ // if (this->mcast_.set_option (IP_MULTICAST_LOOP, 0) == -1 )
+ // ACE_OS::perror (" can't disable loopbacks " ), ACE_OS::exit (1);
+
+ // Register callbacks with the ACE_Reactor.
+ else if (reactor.register_handler (this->mcast_.get_handle (),
+ this,
+ ACE_Event_Handler::READ_MASK) == -1)
+ ACE_ERROR ((LM_ERROR,
+ "%p\n",
+ "can't register with Reactor\n"));
+ // Register the STDIN handler.
+ else if (ACE_Event_Handler::register_stdin_handler (this,
+ ACE_Reactor::instance (),
+ ACE_Thread_Manager::instance ()) == -1)
+ ACE_ERROR ((LM_ERROR,
+ "%p\n",
+ "register_stdin_handler"));
+}
+
+static void
+parse_args (int argc, ACE_TCHAR *argv[])
+{
+ ACE_Get_Opt get_opt (argc, argv, ACE_TEXT("i:u"));
+
+ int c;
+
+ while ((c = get_opt ()) != -1)
+ switch (c)
+ {
+ case 'i':
+ INTERFACE = get_opt.opt_arg ();
+ break;
+ case 'u':
+ // Usage fallthrough.
+ default:
+ ACE_DEBUG ((LM_DEBUG,
+ "%s -i interface\n",
+ argv[0]));
+ ACE_OS::exit (1);
+ }
+}
+
+int
+ACE_TMAIN (int argc, ACE_TCHAR *argv[])
+{
+ parse_args (argc, argv);
+
+ Handler handler (UDP_PORT,
+ MCAST_ADDR,
+ INTERFACE,
+ *ACE_Reactor::instance ());
+
+ // Run the event loop.
+ ACE_Reactor::run_event_loop ();
+
+ ACE_DEBUG ((LM_DEBUG,
+ "talker Done.\n"));
+ return 0;
+}
+
+#else
+int
+ACE_TMAIN (int, ACE_TCHAR *argv[])
+{
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "error: %s must be run on a platform that support IP multicast\n",
+ argv[0]),
+ 0);
+}
+#endif /* ACE_HAS_IP_MULTICAST */
+
diff --git a/ACE/examples/Reactor/Proactor/.cvsignore b/ACE/examples/Reactor/Proactor/.cvsignore
new file mode 100644
index 00000000000..34179361b75
--- /dev/null
+++ b/ACE/examples/Reactor/Proactor/.cvsignore
@@ -0,0 +1,7 @@
+test_cancel
+test_end_event_loop
+test_multiple_loops
+test_post_completions
+test_proactor
+test_timeout
+test_udp_proactor
diff --git a/ACE/examples/Reactor/Proactor/Aio_Platform_Test_C.cpp b/ACE/examples/Reactor/Proactor/Aio_Platform_Test_C.cpp
new file mode 100644
index 00000000000..be720fdef40
--- /dev/null
+++ b/ACE/examples/Reactor/Proactor/Aio_Platform_Test_C.cpp
@@ -0,0 +1,137 @@
+// $Id$
+// ============================================================================
+//
+// = FILENAME
+// aio_platform_test_c.cpp
+//
+// = DESCRITPTION
+// Testing the platform for POSIX Asynchronous I/O. This is the C
+// version of the $ACE_ROOT/tests/Aio_Platform_Test.cpp. Useful
+// to send bug reports.
+//
+// = AUTHOR
+// Programming for the Real World. Bill O. GallMeister.
+// Modified by Alexander Babu Arulanthu <alex@cs.wustl.edu>
+//
+// =====================================================================
+
+
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <signal.h>
+#include <string.h>
+#include <errno.h>
+#include <stdio.h>
+
+#include <limits.h>
+
+#include <aio.h>
+
+int do_sysconf (void);
+int have_asynchio (void);
+
+static int file_handle = -1;
+char mb1 [BUFSIZ + 1];
+char mb2 [BUFSIZ + 1];
+aiocb aiocb1, aiocb2;
+sigset_t completion_signal;
+
+// For testing the <aio> stuff.
+int test_aio_calls (void);
+int issue_aio_calls (void);
+int query_aio_completions (void);
+int setup_signal_delivery (void);
+int do_sysconf (void);
+int have_asynchio (void);
+
+int
+do_sysconf (void)
+{
+ // Call sysconf to find out runtime values.
+ errno = 0;
+#if defined (_SC_LISTIO_AIO_MAX)
+ printf ("Runtime value of LISTIO_AIO_MAX is %d, errno = %d\n",
+ sysconf(_SC_LISTIO_AIO_MAX),
+ errno);
+#else
+ printf ("Runtime value of AIO_LISTIO_MAX is %d, errno = %d\n",
+ sysconf(_SC_AIO_LISTIO_MAX),
+ errno);
+#endif
+
+ errno = 0;
+ printf ("Runtime value of AIO_MAX is %d, errno = %d\n",
+ sysconf (_SC_AIO_MAX),
+ errno);
+
+ errno = 0;
+ printf ("Runtime value of _POSIX_ASYNCHRONOUS_IO is %d, errno = %d\n",
+ sysconf (_SC_ASYNCHRONOUS_IO),
+ errno);
+
+ errno = 0;
+ printf ("Runtime value of _POSIX_REALTIME_SIGNALS is %d, errno = %d\n",
+ sysconf (_SC_REALTIME_SIGNALS),
+ errno);
+
+ errno = 0;
+ printf ("Runtime value of RTSIG_MAX %d, Errno = %d\n",
+ sysconf (_SC_RTSIG_MAX),
+ errno);
+
+ errno = 0;
+ printf ("Runtime value of SIGQUEUE_MAX %d, Errno = %d\n",
+ sysconf (_SC_SIGQUEUE_MAX),
+ errno);
+ return 0;
+}
+
+int
+have_asynchio (void)
+{
+#if defined (_POSIX_ASYNCHRONOUS_IO)
+ // POSIX Asynch IO is present in this system.
+#if defined (_POSIX_ASYNC_IO)
+ // If this is defined and it is not -1, POSIX_ASYNCH is supported
+ // everywhere in the system.
+#if _POSIX_ASYNC_IO == -1
+ printf ("_POSIX_ASYNC_IO = -1.. ASYNCH IO NOT supported at all\n");
+ return -1;
+#else /* Not _POSIX_ASYNC_IO == -1 */
+ printf ("_POSIX_ASYNC_IO = %d\n ASYNCH IO is supported FULLY\n",
+ _POSIX_ASYNC_IO);
+#endif /* _POSIX_ASYNC_IO == -1 */
+
+#else /* Not defined _POSIX_ASYNC_IO */
+ printf ("_POSIX_ASYNC_IO is not defined.\n");
+ printf ("AIO might *not* be supported on some paths\n");
+#endif /* _POSIX_ASYNC_IO */
+
+ // System defined POSIX Values.
+ printf ("System claims to have POSIX_ASYNCHRONOUS_IO\n");
+
+ printf ("_POSIX_AIO_LISTIO_MAX = %d\n", _POSIX_AIO_LISTIO_MAX);
+ printf ("_POSIX_AIO_MAX = %d\n", _POSIX_AIO_MAX);
+
+ // Check and print the run time values.
+ do_sysconf ();
+
+ return 0;
+
+#else /* Not _POSIX_ASYNCHRONOUS_IO */
+ printf ("No support._POSIX_ASYNCHRONOUS_IO itself is not defined\n");
+ return -1;
+#endif /* _POSIX_ASYNCHRONOUS_IO */
+}
+
+int
+main (int, char *[])
+{
+ if (have_asynchio () == 0)
+ printf ("Test successful\n");
+ else
+ printf ("Test not successful\n");
+ return 0;
+}
diff --git a/ACE/examples/Reactor/Proactor/Makefile.am b/ACE/examples/Reactor/Proactor/Makefile.am
new file mode 100644
index 00000000000..7f1bc4b8a57
--- /dev/null
+++ b/ACE/examples/Reactor/Proactor/Makefile.am
@@ -0,0 +1,153 @@
+## Process this file with automake to create Makefile.in
+##
+## $Id$
+##
+## This file was generated by MPC. Any changes made directly to
+## this file will be lost the next time it is generated.
+##
+## MPC Command:
+## /acebuilds/ACE_wrappers-repository/bin/mwc.pl -include /acebuilds/MPC/config -include /acebuilds/MPC/templates -feature_file /acebuilds/ACE_wrappers-repository/local.features -noreldefs -type automake -exclude build,Kokyu
+
+ACE_BUILDDIR = $(top_builddir)
+ACE_ROOT = $(top_srcdir)
+
+noinst_PROGRAMS =
+
+## Makefile.Proactor_Cancel.am
+
+if !BUILD_ACE_FOR_TAO
+noinst_PROGRAMS += test_cancel
+
+test_cancel_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+test_cancel_SOURCES = \
+ test_cancel.cpp \
+ test_cancel.h
+
+test_cancel_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+endif !BUILD_ACE_FOR_TAO
+
+## Makefile.Proactor_End_Event_Loops.am
+
+if !BUILD_ACE_FOR_TAO
+noinst_PROGRAMS += test_end_event_loop
+
+test_end_event_loop_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+test_end_event_loop_SOURCES = \
+ test_end_event_loop.cpp \
+ test_cancel.h \
+ test_proactor.h
+
+test_end_event_loop_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+endif !BUILD_ACE_FOR_TAO
+
+## Makefile.Proactor_Multiple_Loops.am
+
+if !BUILD_ACE_FOR_TAO
+noinst_PROGRAMS += test_multiple_loops
+
+test_multiple_loops_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+test_multiple_loops_SOURCES = \
+ test_multiple_loops.cpp \
+ test_cancel.h \
+ test_proactor.h
+
+test_multiple_loops_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+endif !BUILD_ACE_FOR_TAO
+
+## Makefile.Proactor_Post_Completions.am
+
+if !BUILD_ACE_FOR_TAO
+noinst_PROGRAMS += test_post_completions
+
+test_post_completions_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+test_post_completions_SOURCES = \
+ post_completions.cpp \
+ test_cancel.h \
+ test_proactor.h
+
+test_post_completions_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+endif !BUILD_ACE_FOR_TAO
+
+## Makefile.Proactor_Proactor.am
+
+if !BUILD_ACE_FOR_TAO
+noinst_PROGRAMS += test_proactor
+
+test_proactor_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+test_proactor_SOURCES = \
+ test_proactor.cpp \
+ test_proactor.h
+
+test_proactor_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+endif !BUILD_ACE_FOR_TAO
+
+## Makefile.Proactor_Timeout.am
+
+if !BUILD_ACE_FOR_TAO
+noinst_PROGRAMS += test_timeout
+
+test_timeout_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+test_timeout_SOURCES = \
+ test_timeout.cpp \
+ test_cancel.h \
+ test_proactor.h
+
+test_timeout_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+endif !BUILD_ACE_FOR_TAO
+
+## Makefile.Proactor_Udp_Proactor.am
+
+if !BUILD_ACE_FOR_TAO
+noinst_PROGRAMS += test_udp_proactor
+
+test_udp_proactor_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+test_udp_proactor_SOURCES = \
+ test_udp_proactor.cpp \
+ test_cancel.h \
+ test_proactor.h
+
+test_udp_proactor_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+endif !BUILD_ACE_FOR_TAO
+
+## Clean up template repositories, etc.
+clean-local:
+ -rm -f *~ *.bak *.rpo *.sym lib*.*_pure_* core core.*
+ -rm -f gcctemp.c gcctemp so_locations *.ics
+ -rm -rf cxx_repository ptrepository ti_files
+ -rm -rf templateregistry ir.out
+ -rm -rf ptrepository SunWS_cache Templates.DB
diff --git a/ACE/examples/Reactor/Proactor/Proactor.mpc b/ACE/examples/Reactor/Proactor/Proactor.mpc
new file mode 100644
index 00000000000..c2c52207ca1
--- /dev/null
+++ b/ACE/examples/Reactor/Proactor/Proactor.mpc
@@ -0,0 +1,59 @@
+// -*- MPC -*-
+// $Id$
+
+project(*cancel) : aceexe {
+ avoids += ace_for_tao
+ exename = test_cancel
+ Source_Files {
+ test_cancel.cpp
+ }
+}
+
+project(*end_event_loops) : aceexe {
+ avoids += ace_for_tao
+ exename = test_end_event_loop
+ Source_Files {
+ test_end_event_loop.cpp
+ }
+}
+
+project(*multiple_loops) : aceexe {
+ avoids += ace_for_tao
+ exename = test_multiple_loops
+ Source_Files {
+ test_multiple_loops.cpp
+ }
+}
+
+project(*post_completions) : aceexe {
+ avoids += ace_for_tao
+ exename = test_post_completions
+ Source_Files {
+ post_completions.cpp
+ }
+}
+
+project(*proactor) : aceexe {
+ avoids += ace_for_tao
+ exename = test_proactor
+ Source_Files {
+ test_proactor.cpp
+ }
+}
+
+project(*timeout) : aceexe {
+ avoids += ace_for_tao
+ exename = test_timeout
+ Source_Files {
+ test_timeout.cpp
+ }
+}
+
+project(*udp_proactor) : aceexe {
+ avoids += ace_for_tao
+ exename = test_udp_proactor
+ Source_Files {
+ test_udp_proactor.cpp
+ }
+}
+
diff --git a/ACE/examples/Reactor/Proactor/README b/ACE/examples/Reactor/Proactor/README
new file mode 100644
index 00000000000..29f2a0b1832
--- /dev/null
+++ b/ACE/examples/Reactor/Proactor/README
@@ -0,0 +1,75 @@
+$Id$
+
+This README file lists all the example applications for the Proactor framework.
+
+Test/Example Applications for Proactor:
+=========================================
+
+The following tests are available.
+
+o $ACE_ROOT/tests/Aio_Platform_Test.cpp : Tests basic limits
+ pertaining to the POSIX features
+
+o $ACE_ROOT/examples/Reactor/Proactor/test_aiocb.cpp :
+ This is a C++ program for testing the AIOCB (AIO Control
+ Blocks) based completion approach which uses <aio_suspend> for
+ completion querying.
+
+o $ACE_ROOT/examples/Reactor/Proactor/test_aiosig.cpp : This is a
+ C++ program for testing the Signal based completion approach
+ that uses <sigtimedwait> for completion querying.
+
+o $ACE_ROOT/examples/Reactor/Proactor/test_aiocb_ace.cpp: Portable
+ version of test_aiocb.cpp. (Same as test_aiocb.cpp, but uses
+ ACE_DEBUGs instead of printf's and ACE_Message_Blocks instead
+ of char*'s.
+
+o $ACE_ROOT/examples/Reactor/Proactor/test_aiosig_ace.cpp: Portable
+ version of test_aiosig.cpp. (Same as test_aiosig.cpp, but uses
+ ACE_DEBUGs instead of printf's and ACE_Message_Blocks instead
+ of char*'s.
+
+o test_proactor.cpp (with ACE_POSIX_AIOCB_Proactor) : Test for
+ ACE_Proactor which uses AIOCB (AIO Control Blocks) based
+ completions strategy Proactor. (#define
+ ACE_POSIX_AIOCB_PROACTOR in the config file, but this is the
+ default option)
+
+o test_proactor.cpp (with ACE_POSIX_SIG_Proactor) : Test for
+ ACE_Proactor which uses real time signal based completion
+ strategy proactor. (#define ACE_POSIX_SIG_PROACTOR in the
+ config file)
+
+o test_multiple_loops.cpp : This example application shows how
+ to write programs that combine the Proactor and Reactor event
+ loops. This is possible only on WIN32 platform.
+
+o test_timeout.cpp : Multithreaded application testing the Timers
+ mechanism of the Proactor.
+
+o test_timeout_st.cpp : Single-threaded version of test_timeout.cpp.
+
+o post_completions.cpp : Tests the completion posting mechanism of
+ the Proactor.
+
+o test_end_event_loop.cpp : Tests the event loop mechanism of the
+ Proactor.
+
+o test_cancel.cpp : Tests <cancel> interface of the
+ Asynch_Operation class.
+
+Behavior of POSIX AIO of various platforms:
+==========================================
+
+Sun 5.6 : POSIX4 Real-Time signals implementation is broken in
+ this platform.
+ Only POSIX AIOCB Proactor works in this platform.
+ Therefore, it is not possible to use multiple threads
+ with in the framework.
+
+Sun 5.7 : AIOCB and SIG Proactors work fine.
+
+LynxOS 3.0.0 : <pthread_sigmask> is not available in this
+ platform. So, only AIOCB Proactor works here.
+
+
diff --git a/ACE/examples/Reactor/Proactor/post_completions.cpp b/ACE/examples/Reactor/Proactor/post_completions.cpp
new file mode 100644
index 00000000000..e6545241953
--- /dev/null
+++ b/ACE/examples/Reactor/Proactor/post_completions.cpp
@@ -0,0 +1,306 @@
+// $Id$
+// ============================================================================
+//
+// = FILENAME
+// post_completions.cpp
+//
+// = DESCRITPTION
+// This program demonstrates how to post fake completions to The
+// Proactor. It also shows the how to specify the particular
+// real-time signals to post completions. The Real-time signal
+// based completion strategy is implemented with
+// ACE_POSIX_SIG_PROACTOR.
+// (So, it can be used only if both ACE_HAS_AIO_CALLS and
+// ACE_HAS_POSIX_REALTIME_SIGNALS are defined.)
+// Since it is faking results, you have to pay by knowing and
+// using platform-specific implementation objects for Asynchronous
+// Result classes.
+// This example shows using an arbitrary result class for faking
+// completions. You can also use the predefined Result classes for
+// faking. The factory methods in the Proactor class create the
+// Result objects.
+//
+// = COMPILATION
+// make
+//
+// = RUN
+// ./post_completions
+//
+// = AUTHOR
+// Alexander Babu Arulanthu <alex@cs.wustl.edu>
+//
+// =====================================================================
+
+#include "ace/OS_NS_unistd.h"
+#include "ace/OS_main.h"
+#include "ace/Proactor.h"
+#include "ace/Task.h"
+#include "ace/WIN32_Proactor.h"
+#include "ace/POSIX_Proactor.h"
+#include "ace/Atomic_Op.h"
+#include "ace/Thread_Mutex.h"
+
+// Keep track of how many completions are still expected.
+static ACE_Atomic_Op <ACE_SYNCH_MUTEX, size_t> Completions_To_Go;
+
+
+#if (defined (ACE_WIN32) && !defined (ACE_HAS_WINCE)) || \
+ defined (ACE_HAS_AIO_CALLS)
+// This only works on Win32 platforms and on Unix platforms supporting
+// POSIX aio calls.
+
+#if defined (ACE_HAS_AIO_CALLS)
+#define RESULT_CLASS ACE_POSIX_Asynch_Result
+#elif defined (ACE_WIN32) && !defined (ACE_HAS_WINCE)
+#define RESULT_CLASS ACE_WIN32_Asynch_Result
+#endif /* ACE_HAS_AIO_CALLS */
+
+class My_Result : public RESULT_CLASS
+{
+ // = TITLE
+ //
+ // Result Object that we will post to the Proactor.
+ //
+ // = DESCRIPTION
+ //
+
+public:
+ My_Result (ACE_Handler &handler,
+ const void *act,
+ int signal_number,
+ size_t sequence_number)
+ : RESULT_CLASS (handler.proxy (),
+ act,
+ ACE_INVALID_HANDLE,
+ 0, // Offset
+ 0, // OffsetHigh
+ 0, // Priority
+ signal_number),
+ sequence_number_ (sequence_number)
+ {}
+ // Constructor.
+
+ virtual ~My_Result (void)
+ {}
+ // Destructor.
+
+ void complete (size_t,
+ int success,
+ const void *completion_key,
+ u_long error)
+ // This is the method that will be called by the Proactor for
+ // dispatching the completion. This method generally calls one of
+ // the call back hood methods defined in the ACE_Handler
+ // class. But, we will just handle the completions here.
+ {
+ this->success_ = success;
+ this->completion_key_ = completion_key;
+ this->error_ = error;
+
+ size_t to_go = --Completions_To_Go;
+
+ // Print the completion details.
+ ACE_DEBUG ((LM_DEBUG,
+ "(%t) Completion sequence number %d, success : %d, error : %d, signal_number : %d, %u more to go\n",
+ this->sequence_number_,
+ this->success_,
+ this->error_,
+ this->signal_number (),
+ to_go));
+
+ // Sleep for a while.
+ ACE_OS::sleep (4);
+ }
+
+private:
+ size_t sequence_number_;
+ // Sequence number for the result object.
+};
+
+class My_Handler : public ACE_Handler
+{
+ // = TITLE
+ //
+ // Handler class for faked completions.
+ //
+ // = DESCRIPTION
+ //
+
+public:
+ My_Handler (void) {}
+ // Constructor.
+
+ virtual ~My_Handler (void) {}
+ // Destructor.
+};
+
+class My_Task: public ACE_Task <ACE_NULL_SYNCH>
+{
+ // = TITLE
+ //
+ // Contains thread functions which execute event loops. Each
+ // thread waits for a different signal.
+ //
+public:
+ My_Task (void) {}
+ // Constructor.
+
+ virtual ~My_Task (void) {}
+ // Destructor.
+
+ int open (void *proactor)
+ {
+ // Store the proactor.
+ this->proactor_ = (ACE_Proactor *) proactor;
+
+ // Activate the Task.
+ this->activate (THR_NEW_LWP, 5);
+ return 0;
+ }
+
+ int svc (void)
+ {
+ // Handle events for 13 seconds.
+ ACE_Time_Value run_time (13);
+
+ ACE_DEBUG ((LM_DEBUG, "(%t):Starting svc routine\n"));
+
+ if (this->proactor_->handle_events (run_time) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, "(%t):%p.\n", "Worker::svc"), -1);
+
+ ACE_DEBUG ((LM_DEBUG, "(%t) work complete\n"));
+
+ return 0;
+ }
+
+private:
+ ACE_Proactor *proactor_;
+ // Proactor for this task.
+};
+
+int
+ACE_TMAIN (int argc, ACE_TCHAR *argv[])
+{
+ ACE_UNUSED_ARG (argc);
+ ACE_UNUSED_ARG (argv);
+
+ ACE_DEBUG ((LM_DEBUG,
+ "(%P | %t):Test starts \n"));
+
+ // = Get two POSIX_SIG_Proactors, one with SIGRTMIN and one with
+ // SIGRTMAX.
+
+ ACE_Proactor proactor1;
+ // Proactor1. SIGRTMIN Proactor. (default).
+
+ // = Proactor2. SIGRTMAX Proactor.
+#if defined (ACE_HAS_AIO_CALLS) && defined (ACE_HAS_POSIX_REALTIME_SIGNALS)
+
+ ACE_DEBUG ((LM_DEBUG, "Using ACE_POSIX_SIG_Proactor\n"));
+
+ sigset_t signal_set;
+ // Signal set that we want to mask.
+
+ // Clear the signal set.
+ if (sigemptyset (&signal_set) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Error:%p\n",
+ "sigemptyset failed"),
+ 1);
+
+ // Add the SIGRTMAX to the signal set.
+ if (sigaddset (&signal_set, ACE_SIGRTMAX) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Error:%p\n",
+ "sigaddset failed"),
+ 1);
+
+ // Make the POSIX Proactor.
+ ACE_POSIX_SIG_Proactor posix_proactor (signal_set);
+ // Get the Proactor interface out of it.
+ ACE_Proactor proactor2 (&posix_proactor);
+#else /* ACE_HAS_AIO_CALLS && ACE_HAS_POSIX_REALTIME_SIGNALS */
+ ACE_Proactor proactor2;
+#endif /* ACE_HAS_AIO_CALLS && ACE_HAS_POSIX_REALTIME_SIGNALS */
+
+ // = Create Tasks. One pool of threads to handle completions on
+ // SIGRTMIN and the other one to handle completions on SIGRTMAX.
+ My_Task task1, task2;
+ task1.open (&proactor1);
+ task2.open (&proactor2);
+
+ // Handler for completions.
+ My_Handler handler;
+
+ // = Create a few MyResult objects and post them to Proactor.
+ const size_t NrCompletions (10);
+ My_Result *result_objects [NrCompletions];
+ int signal_number = ACE_SIGRTMAX;
+ size_t ri = 0;
+
+ Completions_To_Go = NrCompletions;
+
+ // Creation.
+ for (ri = 0; ri < NrCompletions; ri++)
+ {
+ // Use RTMIN and RTMAX proactor alternatively, to post
+ // completions.
+ if (ri % 2)
+ signal_number = ACE_SIGRTMIN;
+ else
+ signal_number = ACE_SIGRTMAX;
+ // Create the result.
+ ACE_NEW_RETURN (result_objects [ri],
+ My_Result (handler,
+ 0,
+ signal_number,
+ ri),
+ 1);
+ }
+ ACE_OS::sleep(5);
+ // Post all the result objects.
+ ACE_Proactor *proactor;
+ for (ri = 0; ri < NrCompletions; ri++)
+ {
+ // Use RTMIN and RTMAX Proactor alternatively, to post
+ // completions.
+ if (ri % 2)
+ proactor = &proactor1;
+ else
+ proactor = &proactor2;
+ if (result_objects [ri]->post_completion (proactor->implementation ())
+ == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Test failed\n"),
+ 1);
+ }
+
+ ACE_Thread_Manager::instance ()->wait ();
+
+ int status = 0;
+ size_t to_go = Completions_To_Go.value ();
+ if (size_t (0) != to_go)
+ {
+ ACE_ERROR ((LM_ERROR,
+ "Fail! Expected all completions to finish but %u to go\n",
+ to_go));
+ status = 1;
+ }
+
+ ACE_DEBUG ((LM_DEBUG,
+ "(%P | %t):Test ends\n"));
+ return status;
+}
+
+#else /* ACE_WIN32 && !ACE_HAS_WINCE || ACE_HAS_AIO_CALLS && !ACE_POSIX_AIOCB_PROACTOR*/
+
+int
+main (int, char *[])
+{
+ ACE_DEBUG ((LM_DEBUG,
+ "This example cannot work with AIOCB_Proactor.\n"));
+ return 1;
+}
+
+#endif /* ACE_WIN32 && !ACE_HAS_WINCE || ACE_HAS_AIO_CALLS && !ACE_POSIX_AIOCB_PROACTOR*/
+
diff --git a/ACE/examples/Reactor/Proactor/simple_test_proactor.cpp b/ACE/examples/Reactor/Proactor/simple_test_proactor.cpp
new file mode 100644
index 00000000000..1f4557d7df5
--- /dev/null
+++ b/ACE/examples/Reactor/Proactor/simple_test_proactor.cpp
@@ -0,0 +1,269 @@
+// $Id$
+
+// ============================================================================
+//
+// = LIBRARY
+// examples
+//
+// = FILENAME
+// simple_test_proactor.cpp
+//
+// = DESCRIPTION
+// Very simple version of test_proactor.cpp.
+//
+// = AUTHOR
+// Alexander Babu Arulanthu (alex@cs.wustl.edu)
+//
+// ============================================================================
+
+#include "ace/Service_Config.h"
+#include "ace/Proactor.h"
+#include "ace/Asynch_IO.h"
+#include "ace/Asynch_IO_Impl.h"
+#include "ace/Message_Block.h"
+#include "ace/Get_Opt.h"
+#include "ace/OS_main.h"
+
+ACE_RCSID(Proactor, test_proactor, "simple_test_proactor.cpp,v 1.1 1999/05/18 22:15:30 alex Exp")
+
+#if ((defined (ACE_WIN32) && !defined (ACE_HAS_WINCE)) || (defined (ACE_HAS_AIO_CALLS)))
+ // This only works on Win32 platforms and on Unix platforms supporting
+ // POSIX aio calls.
+
+static ACE_TCHAR *file = ACE_TEXT("simple_test_proactor.cpp");
+static ACE_TCHAR *dump_file = ACE_TEXT("simple_output");
+
+class Simple_Tester : public ACE_Handler
+{
+ // = TITLE
+ //
+ // Simple_Tester
+ //
+ // = DESCRIPTION
+ //
+ // The class will be created by main(). This class reads a block
+ // from the file and write that to the dump file.
+
+public:
+ Simple_Tester (void);
+ // Constructor.
+
+ ~Simple_Tester (void);
+
+ int open (void);
+ // Open the operations and initiate read from the file.
+
+protected:
+ // = These methods are called by the freamwork.
+
+ virtual void handle_read_file (const ACE_Asynch_Read_File::Result &result);
+ // This is called when asynchronous reads from the socket complete.
+
+ virtual void handle_write_file (const ACE_Asynch_Write_File::Result &result);
+ // This is called when asynchronous writes from the socket complete.
+
+private:
+ int initiate_read_file (void);
+
+ ACE_Asynch_Read_File rf_;
+ // rf (read file): for writing from the file.
+
+ ACE_Asynch_Write_File wf_;
+ // ws (write File): for writing to the file.
+
+ ACE_HANDLE input_file_;
+ // File to read from.
+
+ ACE_HANDLE dump_file_;
+ // File for dumping data.
+
+ // u_long file_offset_;
+ // Current file offset
+
+ // u_long file_size_;
+ // File size
+};
+
+
+Simple_Tester::Simple_Tester (void)
+ : input_file_ (ACE_INVALID_HANDLE),
+ dump_file_ (ACE_INVALID_HANDLE)
+{
+}
+
+Simple_Tester::~Simple_Tester (void)
+{
+ ACE_OS::close (this->input_file_);
+ ACE_OS::close (this->dump_file_);
+}
+
+
+int
+Simple_Tester::open (void)
+{
+ // Initialize stuff
+
+ // Open input file (in OVERLAPPED mode)
+ this->input_file_ = ACE_OS::open (file,
+ GENERIC_READ | FILE_FLAG_OVERLAPPED);
+ if (this->input_file_ == ACE_INVALID_HANDLE)
+ ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "ACE_OS::open"), -1);
+
+ // Open dump file (in OVERLAPPED mode)
+ this->dump_file_ = ACE_OS::open (dump_file,
+ O_CREAT | O_RDWR | O_TRUNC | FILE_FLAG_OVERLAPPED,
+ 0644);
+ if (this->dump_file_ == ACE_INVALID_HANDLE)
+ ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "ACE_OS::open"), -1);
+
+ // Open ACE_Asynch_Read_File
+ if (this->rf_.open (*this, this->input_file_) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "ACE_Asynch_Read_File::open"), -1);
+
+ // Open ACE_Asynch_Write_File
+ if (this->wf_.open (*this, this->dump_file_) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "ACE_Asynch_Write_File::open"), -1);
+
+ ACE_DEBUG ((LM_DEBUG,
+ "Simple_Tester::open: Files and Asynch Operations opened sucessfully\n"));
+
+
+ // Start an asynchronous read file
+ if (this->initiate_read_file () == -1)
+ return -1;
+
+ return 0;
+}
+
+
+int
+Simple_Tester::initiate_read_file (void)
+{
+ // Create Message_Block
+ ACE_Message_Block *mb = 0;
+ ACE_NEW_RETURN (mb, ACE_Message_Block (BUFSIZ + 1), -1);
+
+ // Inititiate an asynchronous read from the file
+ if (this->rf_.read (*mb,
+ mb->size () - 1) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "ACE_Asynch_Read_File::read"), -1);
+
+ ACE_DEBUG ((LM_DEBUG,
+ "Simple_Tester:initiate_read_file: Asynch Read File issued sucessfully\n"));
+
+ return 0;
+}
+
+void
+Simple_Tester::handle_read_file (const ACE_Asynch_Read_File::Result &result)
+{
+ ACE_DEBUG ((LM_DEBUG, "handle_read_file called\n"));
+
+ result.message_block ().rd_ptr ()[result.bytes_transferred ()] = '\0';
+
+ ACE_DEBUG ((LM_DEBUG, "********************\n"));
+ ACE_DEBUG ((LM_DEBUG, "%s = %d\n", "bytes_to_read", result.bytes_to_read ()));
+ ACE_DEBUG ((LM_DEBUG, "%s = %d\n", "handle", result.handle ()));
+ ACE_DEBUG ((LM_DEBUG, "%s = %d\n", "bytes_transfered", result.bytes_transferred ()));
+ ACE_DEBUG ((LM_DEBUG, "%s = %d\n", "act", (u_long) result.act ()));
+ ACE_DEBUG ((LM_DEBUG, "%s = %d\n", "success", result.success ()));
+ ACE_DEBUG ((LM_DEBUG, "%s = %d\n", "completion_key", (u_long) result.completion_key ()));
+ ACE_DEBUG ((LM_DEBUG, "%s = %d\n", "error", result.error ()));
+ ACE_DEBUG ((LM_DEBUG, "********************\n"));
+ // Watch out if you need to enable this... the ACE_Log_Record::MAXLOGMSGLEN
+ // value controls to max length of a log record, and a large output
+ // buffer may smash it.
+#if 0
+ ACE_DEBUG ((LM_DEBUG, "%s = %s\n",
+ "message_block",
+ result.message_block ().rd_ptr ()));
+#endif /* 0 */
+
+ if (result.success ())
+ {
+ // Read successful: write this to the file.
+ if (this->wf_.write (result.message_block (),
+ result.bytes_transferred ()) == -1)
+ {
+ ACE_ERROR ((LM_ERROR, "%p\n", "ACE_Asynch_Write_File::write"));
+ return;
+ }
+ }
+}
+
+void
+Simple_Tester::handle_write_file (const ACE_Asynch_Write_File::Result &result)
+{
+ ACE_DEBUG ((LM_DEBUG, "handle_write_File called\n"));
+
+ // Reset pointers
+ result.message_block ().rd_ptr (result.message_block ().rd_ptr () - result.bytes_transferred ());
+
+ result.message_block ().rd_ptr ()[result.bytes_transferred ()] = '\0';
+
+ ACE_DEBUG ((LM_DEBUG, "********************\n"));
+ ACE_DEBUG ((LM_DEBUG, "%s = %d\n", "bytes_to_write", result.bytes_to_write ()));
+ ACE_DEBUG ((LM_DEBUG, "%s = %d\n", "handle", result.handle ()));
+ ACE_DEBUG ((LM_DEBUG, "%s = %d\n", "bytes_transfered", result.bytes_transferred ()));
+ ACE_DEBUG ((LM_DEBUG, "%s = %d\n", "act", (u_long) result.act ()));
+ ACE_DEBUG ((LM_DEBUG, "%s = %d\n", "success", result.success ()));
+ ACE_DEBUG ((LM_DEBUG, "%s = %d\n", "completion_key", (u_long) result.completion_key ()));
+ ACE_DEBUG ((LM_DEBUG, "%s = %d\n", "error", result.error ()));
+ ACE_DEBUG ((LM_DEBUG, "********************\n"));
+ // Watch out if you need to enable this... the ACE_Log_Record::MAXLOGMSGLEN
+ // value controls to max length of a log record, and a large output
+ // buffer may smash it.
+#if 0
+ ACE_DEBUG ((LM_DEBUG, "%s = %s\n",
+ "message_block",
+ result.message_block ().rd_ptr ()));
+#endif /* 0 */
+ ACE_Proactor::end_event_loop ();
+}
+
+static int
+parse_args (int argc, ACE_TCHAR *argv[])
+{
+ ACE_Get_Opt get_opt (argc, argv, ACE_TEXT("f:d:"));
+ int c;
+
+ while ((c = get_opt ()) != EOF)
+ switch (c)
+ {
+ case 'f':
+ file = get_opt.opt_arg ();
+ break;
+ case 'd':
+ dump_file = get_opt.opt_arg ();
+ break;
+ default:
+ ACE_ERROR ((LM_ERROR, "%p.\n",
+ "usage :\n"
+ "-d <dumpfile>\n"
+ "-f <file>\n"));
+ return -1;
+ }
+
+ return 0;
+}
+
+int
+ACE_TMAIN (int argc, ACE_TCHAR *argv[])
+{
+ if (parse_args (argc, argv) == -1)
+ return -1;
+
+ Simple_Tester Simple_Tester;
+
+ if (Simple_Tester.open () == -1)
+ return -1;
+
+ int success = 1;
+
+ // dispatch events
+ success = !(ACE_Proactor::run_event_loop () == -1);
+
+ return success ? 0 : 1;
+}
+
+#endif /* ACE_WIN32 && !ACE_HAS_WINCE || ACE_HAS_AIO_CALLS*/
diff --git a/ACE/examples/Reactor/Proactor/test_aiocb.cpp b/ACE/examples/Reactor/Proactor/test_aiocb.cpp
new file mode 100644
index 00000000000..c9c0d280f1b
--- /dev/null
+++ b/ACE/examples/Reactor/Proactor/test_aiocb.cpp
@@ -0,0 +1,239 @@
+// $Id$
+
+// ============================================================================
+//
+// = LIBRARY
+// proactor
+//
+// = FILENAME
+// test_aiocb.cpp
+//
+// = DESCRIPTION
+// Checkout $ACE_ROOT/examples/Reactor/Proactor/test_aiocb_ace.cpp,
+// which is the ACE'ified version of this program.
+//
+// = COMPILE and RUN
+// % CC -g -o test_aiocb -lrt test_aiocb.cpp
+// % ./test_aiocb
+//
+// = AUTHOR
+// Alexander Babu Arulanthu <alex@cs.wustl.edu>
+//
+// ============================================================================
+
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <signal.h>
+#include <string.h>
+#include <errno.h>
+#include <stdio.h>
+#include <iostream.h>
+
+#include <aio.h>
+
+class Test_Aio
+{
+public:
+ Test_Aio (void);
+ // Default constructor.
+
+ int init (void);
+ // Initting the output file and the buffer.
+
+ int do_aio (void);
+ // Doing the testing stuff.
+
+ ~Test_Aio (void);
+ // Destructor.
+private:
+ int out_fd_;
+ // Output file descriptor.
+
+ struct aiocb *aiocb_write_;
+ // For writing to the file.
+
+ struct aiocb *aiocb_read_;
+ // Reading stuff from the file.
+
+ char *buffer_write_;
+ // The buffer to be written to the out_fd.
+
+ char *buffer_read_;
+ // The buffer to be read back from the file.
+};
+
+Test_Aio::Test_Aio (void)
+ : aiocb_write_ (new struct aiocb),
+ aiocb_read_ (new struct aiocb),
+ buffer_write_ (0),
+ buffer_read_ (0)
+{
+}
+
+Test_Aio::~Test_Aio (void)
+{
+ delete aiocb_write_;
+ delete aiocb_read_;
+ delete buffer_write_;
+ delete buffer_read_;
+}
+
+// Init the output file and init the buffer.
+int
+Test_Aio::init (void)
+{
+ // Open the output file.
+ this->out_fd_ = open ("test_aio.log", O_RDWR | O_CREAT | O_TRUNC, 0666);
+ if (this->out_fd_ == 0)
+ {
+ cout << "Error : Opening file" << endl;
+ return -1;
+ }
+
+ // Init the buffers.
+ this->buffer_write_ = strdup ("Welcome to the world of AIO... AIO Rules !!!");
+ cout << "The buffer : " << this->buffer_write_ << endl;
+ this->buffer_read_ = new char [strlen (this->buffer_write_) + 1];
+ return 0;
+}
+
+// Set the necessary things for the AIO stuff.
+// Write the buffer asynchly.hmm Disable signals.
+// Go on aio_suspend. Wait for completion.
+// Print out the result.
+int
+Test_Aio::do_aio (void)
+{
+ // = Write to the file.
+
+ // Setup AIOCB.
+ this->aiocb_write_->aio_fildes = this->out_fd_;
+ this->aiocb_write_->aio_offset = 0;
+ this->aiocb_write_->aio_buf = this->buffer_write_;
+ this->aiocb_write_->aio_nbytes = strlen (this->buffer_write_);
+ this->aiocb_write_->aio_reqprio = 0;
+ this->aiocb_write_->aio_sigevent.sigev_notify = SIGEV_NONE;
+ //this->this->aiocb_.aio_sigevent.sigev_signo = SIGRTMAX;
+ this->aiocb_write_->aio_sigevent.sigev_value.sival_ptr =
+ (void *) this->aiocb_write_;
+
+ // Fire off the aio write.
+ if (aio_write (this->aiocb_write_) != 0)
+ {
+ perror ("aio_write");
+ return -1;
+ }
+
+ // = Read from that file.
+
+ // Setup AIOCB.
+ this->aiocb_read_->aio_fildes = this->out_fd_;
+ this->aiocb_read_->aio_offset = 0;
+ this->aiocb_read_->aio_buf = this->buffer_read_;
+ this->aiocb_read_->aio_nbytes = strlen (this->buffer_write_);
+ this->aiocb_read_->aio_reqprio = 0;
+ this->aiocb_read_->aio_sigevent.sigev_notify = SIGEV_NONE;
+ //this->this->aiocb_.aio_sigevent.sigev_signo = SIGRTMAX;
+ this->aiocb_read_->aio_sigevent.sigev_value.sival_ptr =
+ (void *) this->aiocb_read_;
+
+ // Fire off the aio write. If it doesnt get queued, carry on to get
+ // the completion for the first one.
+ if (aio_read (this->aiocb_read_) < 0)
+ perror ("aio_read");
+
+ // Wait for the completion on aio_suspend.
+ struct aiocb *list_aiocb[2];
+ list_aiocb [0] = this->aiocb_write_;
+ list_aiocb [1] = this->aiocb_read_;
+
+ // Do suspend till all the aiocbs in the list are done.
+ int done = 0;
+ int return_val = 0;
+ while (!done)
+ {
+ return_val = aio_suspend (list_aiocb,
+ 2,
+ 0);
+ cerr << "Return value :" << return_val << endl;
+
+ // Analyze return and error values.
+ if (list_aiocb[0] != 0)
+ {
+ if (aio_error (list_aiocb [0]) != EINPROGRESS)
+ {
+ if (aio_return (list_aiocb [0]) == -1)
+ {
+ perror ("aio_return");
+ return -1;
+ }
+ else
+ {
+ // Successful. Store the pointer somewhere and make the
+ // entry NULL in the list.
+ this->aiocb_write_ = list_aiocb [0];
+ list_aiocb [0] = 0;
+ }
+ }
+ else
+ cout << "AIO write in progress" << endl;
+ }
+
+ if (list_aiocb[1] != 0)
+ {
+ if (aio_error (list_aiocb [1]) != EINPROGRESS)
+ {
+ int read_return = aio_return (list_aiocb[1]);
+ if (read_return == -1)
+ {
+ perror ("aio_return");
+ return -1;
+ }
+ else
+ {
+ // Successful. Store the pointer somewhere and make the
+ // entry NULL in the list.
+ this->aiocb_read_ = list_aiocb [1];
+ list_aiocb [1] = 0;
+ this->buffer_read_[read_return] = '\0';
+ }
+ }
+ else
+ cout << "AIO read in progress" << endl;
+ }
+
+ // Is it done?
+ if ((list_aiocb [0] == 0) && (list_aiocb [1] == 0))
+ done = 1;
+ }
+
+ cout << "Both the AIO operations done." << endl;
+ cout << "The buffer is :" << this->buffer_read_ << endl;
+
+ return 0;
+}
+
+int
+main (int argc, char **argv)
+{
+ Test_Aio test_aio;
+
+ if (test_aio.init () != 0)
+ {
+ printf ("AIOCB test failed:\n"
+ "ACE_POSIX_AIOCB_PROACTOR may not work in this platform\n");
+ return -1;
+ }
+
+ if (test_aio.do_aio () != 0)
+ {
+ printf ("AIOCB test failed:\n"
+ "ACE_POSIX_AIOCB_PROACTOR may not work in this platform\n");
+ return -1;
+ }
+ printf ("AIOCB test successful:\n"
+ "ACE_POSIX_AIOCB_PROACTOR should work in this platform\n");
+ return 0;
+}
diff --git a/ACE/examples/Reactor/Proactor/test_aiocb_ace.cpp b/ACE/examples/Reactor/Proactor/test_aiocb_ace.cpp
new file mode 100644
index 00000000000..17705de1f03
--- /dev/null
+++ b/ACE/examples/Reactor/Proactor/test_aiocb_ace.cpp
@@ -0,0 +1,259 @@
+// $Id$
+
+// ============================================================================
+//
+// = LIBRARY
+// proactor
+//
+// = FILENAME
+// test_aiocb_ace.cpp
+//
+// = DESCRIPTION
+// This program helps you to test the <aio_*> calls on a
+// platform.
+//
+// Before running this test, make sure the platform can
+// support POSIX <aio_> calls, using
+// ACE_ROOT/tests/Aio_Platform_Test.
+//
+// This program tests the AIOCB (AIO Control Blocks) based
+// completion approach which uses <aio_suspend> for completion
+// querying.
+//
+// If this test is successful, ACE_POSIX_AIOCB_PROACTOR
+// can be used on this platform.
+//
+// = COMPILE and RUN
+// % make
+// % ./test_aiocb_ace
+//
+// = AUTHOR
+// Alexander Babu Arulanthu <alex@cs.wustl.edu>
+//
+// ============================================================================
+
+#include "ace/ACE.h"
+#include "ace/Log_Msg.h"
+#include "ace/os_include/os_aio.h"
+#include "ace/OS_NS_string.h"
+
+class Test_Aio
+{
+public:
+ Test_Aio (void);
+ // Default constructor.
+
+ int init (void);
+ // Initting the output file and the buffer.
+
+ int do_aio (void);
+ // Doing the testing stuff.
+
+ ~Test_Aio (void);
+ // Destructor.
+private:
+ int out_fd_;
+ // Output file descriptor.
+
+ struct aiocb *aiocb_write_;
+ // For writing to the file.
+
+ struct aiocb *aiocb_read_;
+ // Reading stuff from the file.
+
+ char *buffer_write_;
+ // The buffer to be written to the out_fd.
+
+ char *buffer_read_;
+ // The buffer to be read back from the file.
+};
+
+Test_Aio::Test_Aio (void)
+ : aiocb_write_ (0),
+ aiocb_read_ (0),
+ buffer_write_ (0),
+ buffer_read_ (0)
+{
+ ACE_NEW (this->aiocb_write_,
+ struct aiocb);
+ ACE_NEW (this->aiocb_read_,
+ struct aiocb);
+}
+
+Test_Aio::~Test_Aio (void)
+{
+ delete aiocb_write_;
+ delete aiocb_read_;
+ delete buffer_write_;
+ delete buffer_read_;
+}
+
+// Init the output file and init the buffer.
+int
+Test_Aio::init (void)
+{
+ // Open the output file.
+ this->out_fd_ = ACE_OS::open ("test_aio.log",
+ O_RDWR | O_CREAT | O_TRUNC,
+ 0666);
+ if (this->out_fd_ == 0)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Error: Opening file\n"),
+ -1);
+
+ // Init the buffers.
+ this->buffer_write_ = ACE::strnew ("Welcome to the world of AIO... AIO Rules !!!");
+ ACE_DEBUG ((LM_DEBUG,
+ "The buffer : %s\n",
+ this->buffer_write_));
+
+ // Allocate memory for the read buffer.
+ ACE_NEW_RETURN (this->buffer_read_,
+ char [ACE_OS::strlen (this->buffer_write_)],
+ -1);
+
+ return 0;
+}
+
+// Set the necessary things for the AIO stuff.
+// Write the buffer asynchly.hmm Disable signals.
+// Go on aio_suspend. Wait for completion.
+// Print out the result.
+int
+Test_Aio::do_aio (void)
+{
+ // = Write to the file.
+
+ // Setup AIOCB.
+ this->aiocb_write_->aio_fildes = this->out_fd_;
+ this->aiocb_write_->aio_offset = 0;
+ this->aiocb_write_->aio_buf = this->buffer_write_;
+ this->aiocb_write_->aio_nbytes = ACE_OS::strlen (this->buffer_write_);
+ this->aiocb_write_->aio_reqprio = 0;
+ this->aiocb_write_->aio_sigevent.sigev_notify = SIGEV_NONE;
+ //this->this->aiocb_.aio_sigevent.sigev_signo = SIGRTMAX;
+ this->aiocb_write_->aio_sigevent.sigev_value.sival_ptr =
+ (void *) this->aiocb_write_;
+
+ // Fire off the aio write.
+ if (aio_write (this->aiocb_write_) != 0)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%p\n",
+ "aio_write"),
+ -1);
+
+ // = Read from that file.
+
+ // Setup AIOCB.
+ this->aiocb_read_->aio_fildes = this->out_fd_;
+ this->aiocb_read_->aio_offset = 0;
+ this->aiocb_read_->aio_buf = this->buffer_read_;
+ this->aiocb_read_->aio_nbytes = ACE_OS::strlen (this->buffer_write_);
+ this->aiocb_read_->aio_reqprio = 0;
+ this->aiocb_read_->aio_sigevent.sigev_notify = SIGEV_NONE;
+ //this->this->aiocb_.aio_sigevent.sigev_signo = SIGRTMAX;
+ this->aiocb_read_->aio_sigevent.sigev_value.sival_ptr =
+ (void *) this->aiocb_read_;
+
+ // Fire off the aio write. If it doesnt get queued, carry on to get
+ // the completion for the first one.
+ if (aio_read (this->aiocb_read_) < 0)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%p\n",
+ "aio_read"),
+ -1);
+
+ // Wait for the completion on aio_suspend.
+ struct aiocb *list_aiocb[2];
+ list_aiocb [0] = this->aiocb_write_;
+ list_aiocb [1] = this->aiocb_read_;
+
+ // Do suspend till all the aiocbs in the list are done.
+ int to_finish = 2;
+ int return_val = 0;
+ while (to_finish > 0)
+ {
+ return_val = aio_suspend (list_aiocb,
+ to_finish,
+ 0);
+ ACE_DEBUG ((LM_DEBUG,
+ "Result of <aio_suspend> : %d\n",
+ return_val));
+
+ // Analyze return and error values.
+ if (to_finish > 1)
+ {
+ if (aio_error (list_aiocb [1]) != EINPROGRESS)
+ {
+ if (aio_return (list_aiocb [1]) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%p\n",
+ "aio_return, item 1"),
+ -1);
+ else
+ {
+ // Successful. Remember we have one less thing to finish.
+ --to_finish;
+ list_aiocb [1] = 0;
+ }
+ }
+ else
+ ACE_DEBUG ((LM_DEBUG,
+ "aio_error says aio 1 is in progress\n"));
+ }
+
+ if (aio_error (list_aiocb [0]) != EINPROGRESS)
+ {
+ if (aio_return (list_aiocb [0]) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%p\n",
+ "aio_return, item 0"),
+ -1);
+ else
+ {
+ // Successful. Store the pointer somewhere and bump the
+ // read entry up to the front, if it is still not done.
+ --to_finish;
+ list_aiocb [0] = this->aiocb_read_;
+ }
+ }
+ else
+ ACE_DEBUG ((LM_DEBUG,
+ "aio_error says aio 0 is in progress\n"));
+ }
+
+ ACE_DEBUG ((LM_DEBUG,
+ "Both the AIO operations done.\n"
+ "The buffer is : %s\n",
+ this->buffer_read_));
+
+ return 0;
+}
+
+int
+main (int argc, char **argv)
+{
+
+ ACE_UNUSED_ARG (argc);
+ ACE_UNUSED_ARG (argv);
+
+ Test_Aio test_aio;
+
+ if (test_aio.init () != 0)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "AIOCB test failed:\n"
+ "ACE_POSIX_AIOCB_PROACTOR may not work in this platform\n"),
+ -1);
+
+ if (test_aio.do_aio () != 0)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "AIOCB test failed:\n"
+ "ACE_POSIX_AIOCB_PROACTOR may not work in this platform\n"),
+ -1);
+
+ ACE_DEBUG ((LM_DEBUG,
+ "AIOCB test successful:\n"
+ "ACE_POSIX_AIOCB_PROACTOR should work in this platform\n"));
+
+ return 0;
+}
diff --git a/ACE/examples/Reactor/Proactor/test_aiosig.cpp b/ACE/examples/Reactor/Proactor/test_aiosig.cpp
new file mode 100644
index 00000000000..1746a10a49c
--- /dev/null
+++ b/ACE/examples/Reactor/Proactor/test_aiosig.cpp
@@ -0,0 +1,294 @@
+// $Id$
+// ============================================================================
+//
+// = FILENAME
+// test_aiosig.cpp
+//
+// = DESCRITPTION
+// Check out test_aiosig_ace.cpp, the ACE'ified version of this
+// program. This program may not be uptodate.
+//
+// = COMPILATION
+// CC -g -o test_aiosig -lrt test_aiosig.cpp
+//
+// = RUN
+// ./test_aiosig
+//
+// = AUTHOR
+// Programming for the Real World. Bill O. GallMeister.
+// Modified by Alexander Babu Arulanthu <alex@cs.wustl.edu>
+//
+// =====================================================================
+
+
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <signal.h>
+#include <string.h>
+#include <errno.h>
+#include <stdio.h>
+
+#include <limits.h>
+
+#include <aio.h>
+
+int file_handle = -1;
+char mb1 [BUFSIZ + 1];
+char mb2 [BUFSIZ + 1];
+aiocb aiocb1, aiocb2;
+sigset_t completion_signal;
+
+// Function prototypes.
+int setup_signal_delivery (void);
+int issue_aio_calls (void);
+int query_aio_completions (void);
+int test_aio_calls (void);
+int setup_signal_handler (void);
+int setup_signal_handler (int signal_number);
+
+int
+setup_signal_delivery (void)
+{
+ // Make the sigset_t consisting of the completion signal.
+ if (sigemptyset (&completion_signal) == -1)
+ {
+ perror ("Error:Couldnt init the RT completion signal set\n");
+ return -1;
+ }
+
+ if (sigaddset (&completion_signal, SIGRTMIN) == -1)
+ {
+ perror ("Error:Couldnt init the RT completion signal set\n");
+ return -1;
+ }
+
+ // Mask them.
+ if (pthread_sigmask (SIG_BLOCK, &completion_signal, 0) == -1)
+ {
+ perror ("Error:Couldnt maks the RT completion signals\n");
+ return -1;
+ }
+
+ return setup_signal_handler (SIGRTMIN);
+}
+
+int
+issue_aio_calls (void)
+{
+ // Setup AIOCB.
+ aiocb1.aio_fildes = file_handle;
+ aiocb1.aio_offset = 0;
+ aiocb1.aio_buf = mb1;
+ aiocb1.aio_nbytes = BUFSIZ;
+ aiocb1.aio_reqprio = 0;
+ aiocb1.aio_sigevent.sigev_notify = SIGEV_SIGNAL;
+ aiocb1.aio_sigevent.sigev_signo = SIGRTMIN;
+ aiocb1.aio_sigevent.sigev_value.sival_ptr = (void *) &aiocb1;
+
+ // Fire off the aio write.
+ if (aio_read (&aiocb1) == -1)
+ {
+ // Queueing failed.
+ perror ("Error:Asynch_Read_Stream: aio_read queueing failed\n");
+ return -1;
+ }
+
+ // Setup AIOCB.
+ aiocb2.aio_fildes = file_handle;
+ aiocb2.aio_offset = BUFSIZ + 1;
+ aiocb2.aio_buf = mb2;
+ aiocb2.aio_nbytes = BUFSIZ;
+ aiocb2.aio_reqprio = 0;
+ aiocb2.aio_sigevent.sigev_notify = SIGEV_SIGNAL;
+ aiocb2.aio_sigevent.sigev_signo = SIGRTMIN;
+ aiocb2.aio_sigevent.sigev_value.sival_ptr = (void *) &aiocb2;
+
+ // Fire off the aio write.
+ if (aio_read (&aiocb2) == -1)
+ {
+ // Queueing failed.
+ perror ("Error:Asynch_Read_Stream: aio_read queueing failed\n");
+ return -1;
+ }
+ return 0;
+}
+
+int
+query_aio_completions (void)
+{
+ int result = 0;
+ size_t number_of_compleions = 0;
+ for (number_of_compleions = 0;
+ number_of_compleions < 2;
+ number_of_compleions ++)
+ {
+ // Wait for <milli_seconds> amount of time.
+ // @@ Assigning <milli_seconds> to tv_sec.
+ timespec timeout;
+ timeout.tv_sec = INT_MAX;
+ timeout.tv_nsec = 0;
+
+ // To get back the signal info.
+ siginfo_t sig_info;
+
+ // Await the RT completion signal.
+ int sig_return = sigtimedwait (&completion_signal,
+ &sig_info,
+ &timeout);
+
+ // Error case.
+ // If failure is coz of timeout, then return *0* but set
+ // errno appropriately. This is what the WinNT proactor
+ // does.
+ if (sig_return == -1)
+ {
+ perror ("Error:Error waiting for RT completion signals\n");
+ return -1;
+ }
+
+ // RT completion signals returned.
+ if (sig_return != SIGRTMIN)
+ {
+ printf ("Unexpected signal (%d) has been received while waiting for RT Completion Signals\n",
+ sig_return);
+ return -1;
+ }
+
+ // @@ Debugging.
+ printf ("Sig number found in the sig_info block : %d\n",
+ sig_info.si_signo);
+
+ // Is the signo returned consistent?
+ if (sig_info.si_signo != sig_return)
+ {
+ printf ("Inconsistent signal number (%d) in the signal info block\n",
+ sig_info.si_signo);
+ return -1;
+ }
+
+ // @@ Debugging.
+ printf ("Signal code for this signal delivery : %d\n",
+ sig_info.si_code);
+
+ // Is the signal code an aio completion one?
+ if ((sig_info.si_code != SI_ASYNCIO) &&
+ (sig_info.si_code != SI_QUEUE))
+ {
+ printf ("Unexpected signal code (%d) returned on completion querying\n",
+ sig_info.si_code);
+ return -1;
+ }
+
+ // Retrive the aiocb.
+ aiocb* aiocb_ptr = (aiocb *) sig_info.si_value.sival_ptr;
+
+ // Analyze error and return values. Return values are
+ // actually <errno>'s associated with the <aio_> call
+ // corresponding to aiocb_ptr.
+ int error_code = aio_error (aiocb_ptr);
+ if (error_code == -1)
+ {
+ perror ("Error:Invalid control block was sent to <aio_error> for compleion querying\n");
+ return -1;
+ }
+
+ if (error_code != 0)
+ {
+ // Error occurred in the <aio_>call. Return the errno
+ // corresponding to that <aio_> call.
+ printf ("Error:An AIO call has failed:Error code = %d\n",
+ error_code);
+ return -1;
+ }
+
+ // No error occured in the AIO operation.
+ int nbytes = aio_return (aiocb_ptr);
+ if (nbytes == -1)
+ {
+ perror ("Error:Invalid control block was send to <aio_return>\n");
+ return -1;
+ }
+
+ if (number_of_compleions == 0)
+ // Print the buffer.
+ printf ("Number of bytes transferred : %d\n The buffer : %s \n",
+ nbytes,
+ mb1);
+ else
+ // Print the buffer.
+ printf ("Number of bytes transferred : %d\n The buffer : %s \n",
+ nbytes,
+ mb2);
+ }
+ return 0;
+}
+
+int
+test_aio_calls (void)
+{
+ // Set up the input file.
+ // Open file (in SEQUENTIAL_SCAN mode)
+ file_handle = open ("test_aiosig.cpp", O_RDONLY);
+
+ if (file_handle == -1)
+ {
+ perror ("Error:Opening the inputfile");
+ return -1;
+ }
+
+ if (setup_signal_delivery () < 0)
+ return -1;
+
+ if (issue_aio_calls () < 0)
+ return -1;
+
+ if (query_aio_completions () < 0)
+ return -1;
+
+ return 0;
+}
+
+int
+setup_signal_handler (int signal_number)
+{
+ // Setting up the handler(!) for these signals.
+ struct sigaction reaction;
+ sigemptyset (&reaction.sa_mask); // Nothing else to mask.
+ reaction.sa_flags = SA_SIGINFO; // Realtime flag.
+#if defined (SA_SIGACTION)
+ // Lynx says, it is better to set this bit to be portable.
+ reaction.sa_flags &= SA_SIGACTION;
+#endif /* SA_SIGACTION */
+ reaction.sa_sigaction = null_handler; // Null handler.
+ int sigaction_return = sigaction (SIGRTMIN,
+ &reaction,
+ 0);
+ if (sigaction_return == -1)
+ {
+ perror ("Error:Proactor couldnt do sigaction for the RT SIGNAL");
+ return -1;
+ }
+
+ return 0;
+}
+
+void
+null_handler (int /* signal_number */,
+ siginfo_t * /* info */,
+ void * /* context */)
+{
+}
+
+int
+main (int, char *[])
+{
+ if (test_aio_calls () == 0)
+ printf ("RT SIG test successful:\n"
+ "ACE_POSIX_SIG_PROACTOR should work in this platform\n");
+ else
+ printf ("RT SIG test failed:\n"
+ "ACE_POSIX_SIG_PROACTOR may not work in this platform\n");
+ return 0;
+}
diff --git a/ACE/examples/Reactor/Proactor/test_aiosig_ace.cpp b/ACE/examples/Reactor/Proactor/test_aiosig_ace.cpp
new file mode 100644
index 00000000000..34c1b9b5ab2
--- /dev/null
+++ b/ACE/examples/Reactor/Proactor/test_aiosig_ace.cpp
@@ -0,0 +1,358 @@
+// $Id$
+
+// ============================================================================
+//
+// = FILENAME
+// test_aiosig_sig.cpp
+//
+// = DESCRITPTION
+// This program helps you to test the <aio_*> calls on a
+// platform.
+// Before running this test, make sure the platform can
+// support POSIX <aio_> calls, using ACE_ROOT/tests/Aio_Plaform_Test.cpp
+//
+// This program tests the Signal based completion approach which
+// uses <sigtimedwait> for completion querying.
+// If this test is successful, ACE_POSIX_SIG_PROACTOR
+// can be used on this platform.
+//
+// This program is a ACE version of the
+// $ACE_ROOT/examples/Reactor/Proactor/test_aiosig.cpp, with
+// ACE_DEBUGs and Message_Blocks.
+//
+// This test does the following:
+// Issue two <aio_read>s.
+// Assign SIGRTMIN as the notification signal.
+// Mask these signals from delivery.
+// Receive this signal by doing <sigtimedwait>.
+// Wait for two completions (two signals)
+//
+// = COMPILATION
+// make
+//
+// = RUN
+// ./test_aiosig_ace
+//
+// = AUTHOR
+// Programming for the Real World. Bill O. GallMeister.
+// Modified by Alexander Babu Arulanthu <alex@cs.wustl.edu>
+//
+// =====================================================================
+
+#include "ace/Message_Block.h"
+#include "ace/Log_Msg.h"
+#include "ace/os_include/os_aio.h"
+#include "ace/OS_NS_signal.h"
+#include "ace/OS_NS_unistd.h"
+#include "ace/OS_NS_fcntl.h"
+#include "ace/Asynch_IO.h" // for ACE_INFINITE
+
+static ACE_HANDLE file_handle = ACE_INVALID_HANDLE;
+static ACE_Message_Block mb1 (BUFSIZ + 1);
+static ACE_Message_Block mb2 (BUFSIZ + 1);
+static aiocb aiocb1;
+static aiocb aiocb2;
+static aiocb aiocb3;
+static sigset_t completion_signal;
+
+// Function prototypes.
+static int setup_signal_delivery (void);
+static int issue_aio_calls (void);
+static int query_aio_completions (void);
+static int test_aio_calls (void);
+static void null_handler (int signal_number, siginfo_t *info, void *context);
+static int setup_signal_handler (int signal_number);
+
+static int
+setup_signal_delivery (void)
+{
+ // = Mask all the signals.
+
+ sigset_t full_set;
+
+ // Get full set.
+ if (sigfillset (&full_set) != 0)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Error:(%P | %t):%p\n",
+ "sigfillset failed"),
+ -1);
+
+ // Mask them.
+ if (ACE_OS::pthread_sigmask (SIG_SETMASK, &full_set, 0) != 0)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Error:(%P | %t):%p\n",
+ "pthread_sigmask failed"),
+ -1);
+
+ // = Make a mask with SIGRTMIN only. We use only that signal to
+ // issue <aio_>'s.
+
+ if (sigemptyset (&completion_signal) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, "Error: %p\n",
+ "Couldnt init the RT completion signal set"),
+ -1);
+
+ if (sigaddset (&completion_signal,
+ SIGRTMIN) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, "Error: %p\n",
+ "Couldnt init the RT completion signal set"),
+ -1);
+
+ // Set up signal handler for this signal.
+ return setup_signal_handler (SIGRTMIN);
+}
+
+static int
+setup_signal_handler (int signal_number)
+{
+ ACE_UNUSED_ARG (signal_number);
+
+ // Setting up the handler(!) for these signals.
+ struct sigaction reaction;
+ sigemptyset (&reaction.sa_mask); // Nothing else to mask.
+ reaction.sa_flags = SA_SIGINFO; // Realtime flag.
+#if defined (SA_SIGACTION)
+ // Lynx says, it is better to set this bit to be portable.
+ reaction.sa_flags &= SA_SIGACTION;
+#endif /* SA_SIGACTION */
+ reaction.sa_sigaction = null_handler; // Null handler.
+ int sigaction_return = sigaction (SIGRTMIN,
+ &reaction,
+ 0);
+ if (sigaction_return == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, "Error: %p\n",
+ "Proactor couldnt do sigaction for the RT SIGNAL"),
+ -1);
+ return 0;
+}
+
+
+static int
+issue_aio_calls (void)
+{
+ // Setup AIOCB.
+ aiocb1.aio_fildes = file_handle;
+ aiocb1.aio_offset = 0;
+ aiocb1.aio_buf = mb1.wr_ptr ();
+ aiocb1.aio_nbytes = BUFSIZ;
+ aiocb1.aio_reqprio = 0;
+ aiocb1.aio_sigevent.sigev_notify = SIGEV_SIGNAL;
+ aiocb1.aio_sigevent.sigev_signo = SIGRTMIN;
+ aiocb1.aio_sigevent.sigev_value.sival_ptr = (void *) &aiocb1;
+
+ // Fire off the aio read.
+ if (aio_read (&aiocb1) == -1)
+ // Queueing failed.
+ ACE_ERROR_RETURN ((LM_ERROR, "Error: %p\n",
+ "Asynch_Read_Stream: aio_read queueing failed"),
+ -1);
+
+ // Setup AIOCB.
+ aiocb2.aio_fildes = file_handle;
+ aiocb2.aio_offset = BUFSIZ + 1;
+ aiocb2.aio_buf = mb2.wr_ptr ();
+ aiocb2.aio_nbytes = BUFSIZ;
+ aiocb2.aio_reqprio = 0;
+ aiocb2.aio_sigevent.sigev_notify = SIGEV_SIGNAL;
+ aiocb2.aio_sigevent.sigev_signo = SIGRTMIN;
+ aiocb2.aio_sigevent.sigev_value.sival_ptr = (void *) &aiocb2;
+
+ // Fire off the aio read.
+ if (aio_read (&aiocb2) == -1)
+ // Queueing failed.
+ ACE_ERROR_RETURN ((LM_ERROR, "Error: %p\n",
+ "Asynch_Read_Stream: aio_read queueing failed"),
+ -1);
+
+ // Setup sigval.
+ aiocb3.aio_fildes = ACE_INVALID_HANDLE;
+ aiocb3.aio_offset = 0;
+ aiocb3.aio_buf = 0;
+ aiocb3.aio_nbytes = 0;
+ aiocb3.aio_reqprio = 0;
+ aiocb3.aio_sigevent.sigev_notify = SIGEV_SIGNAL;
+ aiocb3.aio_sigevent.sigev_signo = SIGRTMIN;
+ aiocb3.aio_sigevent.sigev_value.sival_ptr = (void *) &aiocb3;
+ sigval value;
+ value.sival_ptr = reinterpret_cast<void *> (&aiocb3);
+ // Queue this one for completion right now.
+ if (sigqueue (ACE_OS::getpid (), SIGRTMIN, value) == -1)
+ // Queueing failed.
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Error: %p\n", "sigqueue"),
+ -1);
+
+ return 0;
+}
+
+static int
+query_aio_completions (void)
+{
+ for (size_t number_of_compleions = 0;
+ number_of_compleions < 3;
+ number_of_compleions ++)
+ {
+ // Wait for <milli_seconds> amount of time. @@ Assigning
+ // <milli_seconds> to tv_sec.
+ timespec timeout;
+ timeout.tv_sec = ACE_INFINITE;
+ timeout.tv_nsec = 0;
+
+ // To get back the signal info.
+ siginfo_t sig_info;
+
+ // Await the RT completion signal.
+ int sig_return = sigtimedwait (&completion_signal,
+ &sig_info,
+ &timeout);
+
+ // Error case.
+ // If failure is coz of timeout, then return *0* but set
+ // errno appropriately. This is what the WinNT proactor
+ // does.
+ if (sig_return == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, "Error: %p\n",
+ "Error waiting for RT completion signals"),
+ -1);
+
+ // RT completion signals returned.
+ if (sig_return != SIGRTMIN)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Unexpected signal (%d) has been received while waiting for RT Completion Signals\n",
+ sig_return),
+ -1);
+
+ // @@ Debugging.
+ ACE_DEBUG ((LM_DEBUG,
+ "Sig number found in the sig_info block : %d\n",
+ sig_info.si_signo));
+
+ // Is the signo returned consistent?
+ if (sig_info.si_signo != sig_return)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Inconsistent signal number (%d) in the signal info block\n",
+ sig_info.si_signo),
+ -1);
+
+ // @@ Debugging.
+ ACE_DEBUG ((LM_DEBUG,
+ "Signal code for this signal delivery : %d\n",
+ sig_info.si_code));
+
+ // Is the signal code an aio completion one?
+ if ((sig_info.si_code != SI_ASYNCIO) &&
+ (sig_info.si_code != SI_QUEUE))
+ ACE_ERROR_RETURN ((LM_DEBUG,
+ "Unexpected signal code (%d) returned on completion querying\n",
+ sig_info.si_code),
+ -1);
+
+ // Retrive the aiocb.
+ aiocb* aiocb_ptr = (aiocb *) sig_info.si_value.sival_ptr;
+ if (aiocb_ptr == &aiocb3)
+ {
+ ACE_ASSERT (sig_info.si_code == SI_QUEUE);
+ ACE_DEBUG ((LM_DEBUG, "sigqueue caught... good\n"));
+ }
+ else
+ {
+ // Analyze error and return values. Return values are
+ // actually <errno>'s associated with the <aio_> call
+ // corresponding to aiocb_ptr.
+ int error_code = aio_error (aiocb_ptr);
+ if (error_code == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, "%p\n",
+ "Invalid control block was sent to <aio_error> for completion querying"),
+ -1);
+
+ if (error_code != 0)
+ // Error occurred in the <aio_>call. Return the errno
+ // corresponding to that <aio_> call.
+ ACE_ERROR_RETURN ((LM_ERROR, "%p\n",
+ "An AIO call has failed"),
+ error_code);
+
+ // No error occured in the AIO operation.
+ int nbytes = aio_return (aiocb_ptr);
+ if (nbytes == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, "%p\n",
+ "Invalid control block was send to <aio_return>"),
+ -1);
+ if (number_of_compleions == 0)
+ {
+ // Print the buffer.
+ ACE_DEBUG ((LM_DEBUG,
+ "\n Number of bytes transferred : %d\n",
+ nbytes));
+ // Note... the dumps of the buffers are disabled because they
+ // may easily overrun the ACE_Log_Msg output buffer. If you need
+ // to turn the on for some reason, be careful of this.
+#if 0
+ ACE_DEBUG ((LM_DEBUG, "The buffer : %s \n", mb1.rd_ptr ()));
+#endif /* 0 */
+ }
+ else
+ {
+ // Print the buffer.
+ ACE_DEBUG ((LM_DEBUG,
+ "\n Number of bytes transferred : %d\n",
+ nbytes));
+#if 0
+ ACE_DEBUG ((LM_DEBUG, "The buffer : %s \n", mb2.rd_ptr ()));
+#endif /* 0 */
+ }
+ }
+ }
+
+ return 0;
+}
+
+static int
+test_aio_calls (void)
+{
+ // Set up the input file.
+ // Open file (in SEQUENTIAL_SCAN mode)
+ file_handle = ACE_OS::open ("test_aiosig_ace.cpp",
+ O_RDONLY);
+
+ if (file_handle == ACE_INVALID_HANDLE)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%p\n",
+ "ACE_OS::open"),
+ -1);
+
+ if (setup_signal_delivery () == -1)
+ return -1;
+
+ if (issue_aio_calls () == -1)
+ return -1;
+
+ if (query_aio_completions () == -1)
+ return -1;
+
+ return 0;
+}
+
+static void
+null_handler (int signal_number,
+ siginfo_t */* info */,
+ void * /* context */)
+{
+ ACE_ERROR ((LM_ERROR,
+ "Error:%s:Signal number %d\n"
+ "Mask all the RT signals for this thread",
+ "ACE_POSIX_SIG_Proactor::null_handler called",
+ signal_number));
+}
+
+int
+main (int, char *[])
+{
+ if (test_aio_calls () == 0)
+ printf ("RT SIG test successful:\n"
+ "ACE_POSIX_SIG_PROACTOR should work in this platform\n");
+ else
+ printf ("RT SIG test failed:\n"
+ "ACE_POSIX_SIG_PROACTOR may not work in this platform\n");
+ return 0;
+}
diff --git a/ACE/examples/Reactor/Proactor/test_cancel.cpp b/ACE/examples/Reactor/Proactor/test_cancel.cpp
new file mode 100644
index 00000000000..c10f8e9be2c
--- /dev/null
+++ b/ACE/examples/Reactor/Proactor/test_cancel.cpp
@@ -0,0 +1,246 @@
+// $Id$
+
+// ============================================================================
+//
+// = LIBRARY
+// examples
+//
+// = FILENAME
+// test_cancel.cpp
+//
+// = DESCRIPTION
+// This program tests cancelling an Asynchronous Operation in the
+// Proactor framework.
+//
+// This tests accepts a connection and issues an Asynchronous Read
+// Stream. It reads <read_size> (option -s) number of bytes and
+// when this operation completes, it issues another Asynchronous
+// Read Stream to <read_size> and immediately calls <cancel> to
+// cancel the operation and so the program exits closing the
+// connection.
+//
+// Works fine on NT. On Solaris platforms, the asynch read is
+// pending, but the cancel returns with the value <AIO_ALLDONE>
+// indicating all the operations in that handle are done.
+// But, LynxOS has a good <aio_cancel> implementation. It works
+// fine.
+//
+// = RUN
+// ./test_cancel -p <port_number>
+// Then telnet to this port and send <read_size> bytes and your
+// connection should get closed down.
+//
+// = AUTHOR
+// Irfan Pyarali (irfan@cs.wustl.edu)
+//
+// ============================================================================
+
+#include "ace/OS_main.h"
+#include "ace/Service_Config.h"
+#include "ace/Proactor.h"
+#include "ace/Asynch_IO.h"
+#include "ace/Asynch_IO_Impl.h"
+#include "ace/Asynch_Acceptor.h"
+#include "ace/INET_Addr.h"
+#include "ace/SOCK_Connector.h"
+#include "ace/SOCK_Acceptor.h"
+#include "ace/SOCK_Stream.h"
+#include "ace/Message_Block.h"
+#include "ace/Get_Opt.h"
+#include "ace/Log_Msg.h"
+#include "ace/OS_NS_sys_socket.h"
+
+ACE_RCSID (Proactor, test_proactor, "$Id$")
+
+#if ((defined (ACE_WIN32) && !defined (ACE_HAS_WINCE)) || (defined (ACE_HAS_AIO_CALLS)))
+ // This only works on Win32 platforms and on Unix platforms supporting
+ // POSIX aio calls.
+
+#include "test_cancel.h"
+
+static u_short port = ACE_DEFAULT_SERVER_PORT;
+static int done = 0;
+static int read_size = 2;
+
+
+Receiver::Receiver (void)
+ : mb_ (read_size + 1),
+ handle_ (ACE_INVALID_HANDLE)
+{
+}
+
+Receiver::~Receiver (void)
+{
+ ACE_DEBUG ((LM_DEBUG,
+ "Receiver: Closing down Remote connection:%d\n",
+ this->handle_));
+
+ ACE_OS::closesocket (this->handle_);
+}
+
+void
+Receiver::open (ACE_HANDLE handle,
+ ACE_Message_Block &)
+{
+ // New connection, initiate stuff
+
+ ACE_DEBUG ((LM_DEBUG, "%N:%l:Receiver::open called\n"));
+
+ // Cache the new connection
+ this->handle_ = handle;
+
+ // Initiate ACE_Asynch_Read_Stream
+ if (this->rs_.open (*this, this->handle_) == -1)
+ {
+ ACE_ERROR ((LM_ERROR, "%p\n", "ACE_Asynch_Read_Stream::open"));
+ return;
+ }
+
+ // Try to read <n> bytes from the stream.
+
+ ACE_DEBUG ((LM_DEBUG,
+ "Receiver::open: Issuing Asynch Read of (%d) bytes from the stream\n",
+ read_size));
+
+ if (this->rs_.read (this->mb_,
+ read_size) == -1)
+ ACE_ERROR ((LM_ERROR,
+ "%p\n",
+ "Receiver::open: Failed to issue the read"));
+}
+
+void
+Receiver::handle_read_stream (const ACE_Asynch_Read_Stream::Result &result)
+{
+ ACE_DEBUG ((LM_DEBUG, "handle_read_stream called\n"));
+
+ // Reset pointers
+ result.message_block ().rd_ptr ()[result.bytes_transferred ()] = '\0';
+
+ ACE_DEBUG ((LM_DEBUG, "********************\n"));
+ ACE_DEBUG ((LM_DEBUG, "%s = %d\n", "bytes_to_read", result.bytes_to_read ()));
+ ACE_DEBUG ((LM_DEBUG, "%s = %d\n", "handle", result.handle ()));
+ ACE_DEBUG ((LM_DEBUG, "%s = %d\n", "bytes_transfered", result.bytes_transferred ()));
+ ACE_DEBUG ((LM_DEBUG, "%s = %d\n", "act", (u_long) result.act ()));
+ ACE_DEBUG ((LM_DEBUG, "%s = %d\n", "success", result.success ()));
+ ACE_DEBUG ((LM_DEBUG, "%s = %d\n", "completion_key", (u_long) result.completion_key ()));
+ ACE_DEBUG ((LM_DEBUG, "%s = %d\n", "error", result.error ()));
+ ACE_DEBUG ((LM_DEBUG, "********************\n"));
+ ACE_DEBUG ((LM_DEBUG, "%s = %s\n", "message_block", result.message_block ().rd_ptr ()));
+
+ if (result.success () && !result.error ())
+ {
+ // Successful read: No error.
+
+ // Set the pointers back in the message block.
+ result.message_block ().wr_ptr (result.message_block ().rd_ptr ());
+
+ // Issue another read, but immediately cancel it.
+
+ // Issue the read.
+
+ ACE_DEBUG ((LM_DEBUG,
+ "Issuing Asynch Read of (%d) bytes from the stream\n",
+ read_size));
+
+ if (this->rs_.read (this->mb_,
+ read_size) == -1)
+ ACE_ERROR ((LM_ERROR,
+ "%p\n",
+ "Receiver::handle_read_stream: Failed to issue the read"));
+
+ // Cancel the read.
+
+ ACE_DEBUG ((LM_DEBUG,
+ "Cacelling Asynch Read "));
+
+ int ret_val = this->rs_.cancel ();
+ if (ret_val == -1)
+ ACE_ERROR ((LM_ERROR,
+ "%p\n",
+ "Receiver::handle_read_stream: Failed to cancel the read"));
+
+ ACE_DEBUG ((LM_DEBUG, "Asynch IO : Cancel : Result = %d\n",
+ ret_val));
+ }
+ else
+ {
+ done = 1;
+
+ ACE_DEBUG ((LM_DEBUG, "Receiver completed\n"));
+
+ // Print the error message if any.
+ if (result.error () != 0)
+ {
+ errno = result.error ();
+
+ ACE_ERROR ((LM_ERROR,
+ "%p\n",
+ "Asynch Read Stream Error: "));
+ }
+ }
+}
+
+static int
+parse_args (int argc, ACE_TCHAR *argv[])
+{
+ ACE_Get_Opt get_opt (argc, argv, ACE_TEXT("p:s:"));
+ int c;
+
+ while ((c = get_opt ()) != EOF)
+ switch (c)
+ {
+ case 'p':
+ port = ACE_OS::atoi (get_opt.opt_arg ());
+ break;
+ case 's':
+ read_size = ACE_OS::atoi (get_opt.opt_arg ());
+ break;
+ default:
+ ACE_ERROR ((LM_ERROR, "%p.\n",
+ "usage :\n"
+ "-p <port>\n"
+ "-s <read_size>\n"));
+ return -1;
+ }
+
+ return 0;
+}
+
+int
+ACE_TMAIN (int argc, ACE_TCHAR *argv[])
+{
+ if (parse_args (argc, argv) == -1)
+ return -1;
+
+ // Note: acceptor parameterized by the Receiver
+ ACE_Asynch_Acceptor<Receiver> acceptor;
+
+ // Listening passively.
+ if (acceptor.open (ACE_INET_Addr (port),
+ read_size,
+ 1) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "ACE:acceptor::open failed\n"),
+ 1);
+
+ int success = 1;
+
+ while (success > 0 && !done)
+ // dispatch events
+ success = ACE_Proactor::instance ()->handle_events ();
+
+ return 0;
+}
+
+#else /* ACE_WIN32 && !ACE_HAS_WINCE || ACE_HAS_AIO_CALLS*/
+
+int
+ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ ACE_DEBUG ((LM_DEBUG,
+ "This example does not work on this platform.\n"));
+ return 1;
+}
+
+#endif /* ACE_WIN32 && !ACE_HAS_WINCE || ACE_HAS_AIO_CALLS*/
diff --git a/ACE/examples/Reactor/Proactor/test_cancel.h b/ACE/examples/Reactor/Proactor/test_cancel.h
new file mode 100644
index 00000000000..45c4bfbc85b
--- /dev/null
+++ b/ACE/examples/Reactor/Proactor/test_cancel.h
@@ -0,0 +1,47 @@
+/*
+** $Id$
+*/
+
+#ifndef _TEST_CANCEL_H
+#define _TEST_CANCEL_H
+
+#include "ace/Asynch_IO.h"
+
+class Receiver : public ACE_Service_Handler
+{
+ // = TITLE
+ //
+ // Receiver
+ //
+ // = DESCRIPTION
+ //
+ // The class will be created by ACE_Asynch_Acceptor when new
+ // connections arrive. This class will then receive data from
+ // the network connection and dump it to a file.
+
+public:
+ Receiver (void);
+ ~Receiver (void);
+
+ virtual void open (ACE_HANDLE handle,
+ ACE_Message_Block &message_block);
+ // This is called after the new connection has been accepted.
+
+protected:
+ // These methods are called by the framework
+
+ virtual void handle_read_stream (const ACE_Asynch_Read_Stream::Result &result);
+ // This is called when asynchronous read from the socket complete
+
+private:
+ ACE_Asynch_Read_Stream rs_;
+ // rs (read stream): for reading from a socket
+
+ ACE_Message_Block mb_;
+ // Message block to read from the stream.
+
+ ACE_HANDLE handle_;
+ // Handle for IO to remote peer
+};
+
+#endif /* _TEST_CANCEL_H */
diff --git a/ACE/examples/Reactor/Proactor/test_end_event_loop.cpp b/ACE/examples/Reactor/Proactor/test_end_event_loop.cpp
new file mode 100644
index 00000000000..096f77b089d
--- /dev/null
+++ b/ACE/examples/Reactor/Proactor/test_end_event_loop.cpp
@@ -0,0 +1,168 @@
+// $Id$
+// ============================================================================
+//
+// = FILENAME
+// test_end_event_loop.cpp
+//
+// = DESCRITPTION
+// This program tests the event loop mechanism of the
+// Proactor. To end the event loop, threads that are blocked in
+// waiting for completions are woken up and the event loop comes
+// to the end. This is tested in this program.
+//
+// Threads are doing <run_event_loop> with/without time_out
+// values and the main thread calls <end_event_loop>.
+//
+// = COMPILATION
+// make
+//
+// = RUN
+// ./test_end_event_loop
+//
+// = AUTHOR
+// Alexander Babu Arulanthu <alex@cs.wustl.edu>
+//
+// =====================================================================
+
+#include "ace/OS_NS_unistd.h"
+#include "ace/Proactor.h"
+#include "ace/Task.h"
+#include "ace/WIN32_Proactor.h"
+#include "ace/POSIX_Proactor.h"
+#include "ace/OS_main.h"
+
+#if ((defined (ACE_WIN32) && !defined (ACE_HAS_WINCE)) || \
+ (defined (ACE_HAS_AIO_CALLS)) && !defined (ACE_POSIX_AIOCB_PROACTOR))
+// This only works on Win32 platforms and on Unix platforms supporting
+// POSIX aio calls.
+
+class My_Task: public ACE_Task <ACE_NULL_SYNCH>
+{
+ // = TITLE
+ //
+ // Contains thread functions which execute event loops. Each
+ // thread waits for a different signal.
+ //
+public:
+ // Constructor.
+ My_Task (void)
+ : time_flag_ (0)
+ {}
+
+
+ virtual ~My_Task (void) {}
+ // Destructor.
+
+ // If time_flag is zero do the eventloop indefinitely, otherwise do
+ // it for finite amount of time (13secs!!!).
+ int open (void *timed_event_loop)
+ {
+ // Set the local variable.
+ if (timed_event_loop == 0)
+ this->time_flag_ = 0;
+ else
+ this->time_flag_ = 1;
+
+ // Spawn the threads.
+ if (this->activate (THR_NEW_LWP, 5) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%N:%l:%p\n",
+ "My_Task:open: <activate> failed"),
+ -1);
+
+ return 0;
+ }
+
+ // Thread function.
+ int svc (void)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ "(%P|%t):Starting svc routine\n"));
+
+ if (this->time_flag_)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ "(%P|%t):Going to do *timed* <run_event_loop> \n"));
+
+ ACE_Time_Value run_time (13);
+
+ if (ACE_Proactor::instance ()->run_event_loop (run_time) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, "(%P|%t):%p.\n",
+ "<Proactor::run_event_loop> failed"),
+ -1);
+ }
+ else
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ "(%P|%t):Going to do *indefinite* <run_event_loop> \n"));
+
+ if (ACE_Proactor::instance ()->run_event_loop () == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, "(%P|%t):%p.\n",
+ "<Proactor::run_event_loop> failed"),
+ -1);
+ }
+ return 0;
+ };
+
+private:
+ int time_flag_;
+ // If zero, indefinite event loop, otherwise timed event loop.
+};
+
+int
+ACE_TMAIN (int argc, ACE_TCHAR *argv [])
+{
+ ACE_UNUSED_ARG (argc);
+ ACE_UNUSED_ARG (argv);
+
+ ACE_DEBUG ((LM_DEBUG,
+ "(%P | %t):Test starts \n"));
+
+ // Let us get the singleton proactor created here. This is very
+ // important. This will mask the signal used in the Proactor masked
+ // for the main thread (and all the threads).
+ ACE_Proactor *proactor = ACE_Proactor::instance ();
+ ACE_UNUSED_ARG (proactor);
+
+ My_Task task1, task2;
+
+ // Test the indefinite run event loop.
+ if (task1.open (0) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%N:%l:(%P | %t):Failed to <open> the task\n"),
+ 1);
+
+ // Test the indefinite run event loop. Just pass a non-zero.
+ if (task2.open ((void *)&task2) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%N:%l:(%P | %t):Failed to <open> the task\n"),
+ 1);
+
+ // Give a gap.
+ ACE_OS::sleep (3);
+
+ // End the event loop.
+ if (ACE_Proactor::instance ()->end_event_loop () == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%N:%l:(%P | %t):Failed to <end_event_loop>\n"),
+ 1);
+
+ ACE_Thread_Manager::instance ()->wait ();
+
+ ACE_DEBUG ((LM_DEBUG,
+ "(%P | %t):Test ends\n"));
+ return 0;
+}
+
+#else /* ACE_WIN32 && !ACE_HAS_WINCE || ACE_HAS_AIO_CALLS && !ACE_POSIX_AIOCB_PROACTOR*/
+
+int
+main (int, char *[])
+{
+ ACE_DEBUG ((LM_DEBUG,
+ "This example cannot work with AIOCB_Proactor.\n"));
+ return 1;
+}
+
+#endif /* ACE_WIN32 && !ACE_HAS_WINCE || ACE_HAS_AIO_CALLS && !ACE_POSIX_AIOCB_PROACTOR*/
+
diff --git a/ACE/examples/Reactor/Proactor/test_multiple_loops.cpp b/ACE/examples/Reactor/Proactor/test_multiple_loops.cpp
new file mode 100644
index 00000000000..ac4228ab641
--- /dev/null
+++ b/ACE/examples/Reactor/Proactor/test_multiple_loops.cpp
@@ -0,0 +1,140 @@
+// $Id$
+
+// ============================================================================
+//
+// = LIBRARY
+// examples
+//
+// = FILENAME
+// test_multiple_loops.cpp
+//
+// = DESCRIPTION
+//
+// This example application shows how to write programs that
+// combine the Proactor and Reactor event loops. This is possible
+// only on WIN32 platform.
+//
+// = AUTHOR
+// Irfan Pyarali
+//
+// ============================================================================
+
+#include "ace/Task.h"
+#include "ace/Proactor.h"
+#include "ace/WIN32_Proactor.h"
+#include "ace/Atomic_Op.h"
+#include "ace/OS_NS_unistd.h"
+
+ACE_RCSID(Proactor, test_multiple_loops, "$Id$")
+
+#if (defined (ACE_WIN32) && !defined (ACE_HAS_WINCE))
+
+class Timeout_Handler : public ACE_Handler, public ACE_Event_Handler
+{
+ // = TITLE
+ // Generic timeout handler.
+
+public:
+ Timeout_Handler (void)
+ {
+ }
+
+ // This is called by the Proactor. This is declared in ACE_Handler.
+ virtual void handle_time_out (const ACE_Time_Value &tv,
+ const void *arg)
+ {
+ // Print out when timeouts occur.
+ ACE_DEBUG ((LM_DEBUG, "(%t) %d timeout occurred for %s @ %d.\n",
+ ++count_,
+ (char *) arg,
+ tv.sec ()));
+
+ // Since there is only one thread that can do the timeouts in
+ // Reactor, lets keep the handle_timeout short for that
+ // thread.
+ if (ACE_OS::strcmp ((char *) arg, "Proactor") == 0)
+ // Sleep for a while
+ ACE_OS::sleep (1);
+ }
+
+ // This method is declared in ACE_Event_Handler.
+ virtual int handle_timeout (const ACE_Time_Value &tv,
+ const void *arg)
+ {
+ this->handle_time_out (tv, arg);
+ return 0;
+ }
+
+private:
+ ACE_Atomic_Op <ACE_Thread_Mutex, int> count_;
+};
+
+class Worker : public ACE_Task <ACE_NULL_SYNCH>
+{
+public:
+
+ // Thread fuction.
+ int svc (void)
+ {
+ ACE_DEBUG ((LM_DEBUG, "(%t) Worker started\n"));
+
+ // Handle events for 13 seconds.
+ ACE_Time_Value run_time (13);
+
+ // Try to become the owner
+ ACE_Reactor::instance ()->owner (ACE_Thread::self ());
+
+ if (ACE_Reactor::run_event_loop (run_time) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, "%p.\n", "Worker::svc"), -1);
+ else
+ ACE_DEBUG ((LM_DEBUG, "(%t) work complete\n"));
+
+ return 0;
+ }
+};
+
+int
+ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ Timeout_Handler handler;
+ ACE_WIN32_Proactor win32_proactor (0, 1);
+ ACE_Proactor proactor (&win32_proactor, 0, 0);
+
+ ACE_Reactor::instance ()->register_handler (proactor.implementation ());
+
+ // Register a 2 second timer.
+ ACE_Time_Value foo_tv (2);
+ if (proactor.schedule_timer (handler,
+ (void *) "Proactor",
+ ACE_Time_Value::zero,
+ foo_tv) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "schedule_timer"), -1);
+
+ // Register a 3 second timer.
+ ACE_Time_Value bar_tv (3);
+ if (ACE_Reactor::instance ()->schedule_timer (&handler,
+ (void *) "Reactor",
+ ACE_Time_Value::zero,
+ bar_tv) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "schedule_timer"), -1);
+
+ Worker worker;
+
+ if (worker.activate (THR_NEW_LWP, 10) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, "%p.\n", "main"), -1);
+
+ ACE_Thread_Manager::instance ()->wait ();
+
+ // Remove from reactor
+ ACE_Reactor::instance ()->remove_handler (&proactor,
+ ACE_Event_Handler::DONT_CALL);
+
+ return 0;
+}
+#else
+int
+main (int, char *[])
+{
+ return 0;
+}
+#endif /* ACE_WIN32 && !ACE_HAS_WINCE */
diff --git a/ACE/examples/Reactor/Proactor/test_proactor.cpp b/ACE/examples/Reactor/Proactor/test_proactor.cpp
new file mode 100644
index 00000000000..035a2facf6a
--- /dev/null
+++ b/ACE/examples/Reactor/Proactor/test_proactor.cpp
@@ -0,0 +1,679 @@
+// $Id$
+
+// ============================================================================
+//
+// = LIBRARY
+// examples
+//
+// = FILENAME
+// test_proactor.cpp
+//
+// = DESCRIPTION
+// This program illustrates how the <ACE_Proactor> can be used to
+// implement an application that does various asynchronous
+// operations.
+//
+// = AUTHOR
+// Irfan Pyarali <irfan@cs.wustl.edu>
+//
+// ============================================================================
+
+#include "ace/OS_NS_string.h"
+#include "ace/OS_main.h"
+#include "ace/Service_Config.h"
+#include "ace/Proactor.h"
+#include "ace/Asynch_IO.h"
+#include "ace/Asynch_IO_Impl.h"
+#include "ace/Asynch_Acceptor.h"
+#include "ace/INET_Addr.h"
+#include "ace/SOCK_Connector.h"
+#include "ace/SOCK_Acceptor.h"
+#include "ace/SOCK_Stream.h"
+#include "ace/Message_Block.h"
+#include "ace/Get_Opt.h"
+#include "ace/Log_Msg.h"
+#include "ace/OS_NS_sys_stat.h"
+#include "ace/OS_NS_sys_socket.h"
+#include "ace/OS_NS_unistd.h"
+#include "ace/OS_NS_fcntl.h"
+
+ACE_RCSID(Proactor, test_proactor, "$Id$")
+
+#if ((defined (ACE_WIN32) && !defined (ACE_HAS_WINCE)) || (defined (ACE_HAS_AIO_CALLS)))
+ // This only works on Win32 platforms and on Unix platforms supporting
+ // POSIX aio calls.
+
+#include "test_proactor.h"
+
+
+// Host that we're connecting to.
+static ACE_TCHAR *host = 0;
+
+// Port that we're receiving connections on.
+static u_short port = ACE_DEFAULT_SERVER_PORT;
+
+// File that we're sending.
+static const ACE_TCHAR *file = ACE_TEXT("test_proactor.cpp");
+
+// Name of the output file.
+static const ACE_TCHAR *dump_file = ACE_TEXT("output");
+
+// Keep track of when we're done.
+static int done = 0;
+
+// Size of each initial asynchronous <read> operation.
+static int initial_read_size = BUFSIZ;
+
+
+Receiver::Receiver (void)
+ : dump_file_ (ACE_INVALID_HANDLE),
+ handle_ (ACE_INVALID_HANDLE)
+{
+}
+
+Receiver::~Receiver (void)
+{
+ ACE_OS::close (this->dump_file_);
+ ACE_OS::closesocket (this->handle_);
+}
+
+void
+Receiver::open (ACE_HANDLE handle,
+ ACE_Message_Block &message_block)
+{
+ ACE_DEBUG ((LM_DEBUG,
+ "%N:%l:Receiver::open called\n"));
+
+ // New connection, so initiate stuff.
+
+ // Cache the new connection
+ this->handle_ = handle;
+
+ // File offset starts at zero
+ this->file_offset_ = 0;
+
+ // Open dump file (in OVERLAPPED mode)
+ this->dump_file_ = ACE_OS::open (dump_file,
+ O_CREAT | O_RDWR | O_TRUNC | \
+ FILE_FLAG_OVERLAPPED);
+ if (this->dump_file_ == ACE_INVALID_HANDLE)
+ {
+ ACE_ERROR ((LM_ERROR,
+ "%p\n",
+ "ACE_OS::open"));
+ return;
+ }
+
+ // Initiate <ACE_Asynch_Write_File>.
+ if (this->wf_.open (*this,
+ this->dump_file_) == -1)
+ {
+ ACE_ERROR ((LM_ERROR,
+ "%p\n",
+ "ACE_Asynch_Write_File::open"));
+ return;
+ }
+
+ // Initiate <ACE_Asynch_Read_Stream>.
+ if (this->rs_.open (*this, this->handle_) == -1)
+ {
+ ACE_ERROR ((LM_ERROR,
+ "%p\n",
+ "ACE_Asynch_Read_Stream::open"));
+ return;
+ }
+
+ // Fake the result and make the <handle_read_stream> get
+ // called. But, not, if there is '0' is transferred.
+ if (message_block.length () != 0)
+ {
+ // Duplicate the message block so that we can keep it around.
+ ACE_Message_Block &duplicate =
+ *message_block.duplicate ();
+
+ // Fake the result so that we will get called back.
+ ACE_Asynch_Read_Stream_Result_Impl *fake_result =
+ ACE_Proactor::instance ()->create_asynch_read_stream_result (this->proxy (),
+ this->handle_,
+ duplicate,
+ initial_read_size,
+ 0,
+ ACE_INVALID_HANDLE,
+ 0,
+ 0);
+
+ size_t bytes_transferred = message_block.length ();
+
+ // <complete> for Accept would have already moved the <wr_ptr>
+ // forward. Update it to the beginning position.
+ duplicate.wr_ptr (duplicate.wr_ptr () - bytes_transferred);
+
+ // This will call the callback.
+ fake_result->complete (message_block.length (),
+ 1,
+ 0);
+
+ // Zap the fake result.
+ delete fake_result;
+ }
+ else
+ // Otherwise, make sure we proceed. Initiate reading the socket
+ // stream.
+ if (this->initiate_read_stream () == -1)
+ return;
+}
+
+int
+Receiver::initiate_read_stream (void)
+{
+ // Create a new <Message_Block>. Note that this message block will
+ // be used both to <read> data asynchronously from the socket and to
+ // <write> data asynchronously to the file.
+ ACE_Message_Block *mb = 0;
+ ACE_NEW_RETURN (mb,
+ ACE_Message_Block (BUFSIZ + 1),
+ -1);
+
+ // Inititiate read
+ if (this->rs_.read (*mb,
+ mb->size () - 1) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%p\n",
+ "ACE_Asynch_Read_Stream::read"),
+ -1);
+ return 0;
+}
+
+void
+Receiver::handle_read_stream (const ACE_Asynch_Read_Stream::Result &result)
+{
+ ACE_DEBUG ((LM_DEBUG,
+ "handle_read_stream called\n"));
+
+ // Reset pointers.
+ result.message_block ().rd_ptr ()[result.bytes_transferred ()] = '\0';
+
+ ACE_DEBUG ((LM_DEBUG, "********************\n"));
+ ACE_DEBUG ((LM_DEBUG, "%s = %d\n", "bytes_to_read", result.bytes_to_read ()));
+ ACE_DEBUG ((LM_DEBUG, "%s = %d\n", "handle", result.handle ()));
+ ACE_DEBUG ((LM_DEBUG, "%s = %d\n", "bytes_transfered", result.bytes_transferred ()));
+ ACE_DEBUG ((LM_DEBUG, "%s = %d\n", "act", (u_long) result.act ()));
+ ACE_DEBUG ((LM_DEBUG, "%s = %d\n", "success", result.success ()));
+ ACE_DEBUG ((LM_DEBUG, "%s = %d\n", "completion_key", (u_long) result.completion_key ()));
+ ACE_DEBUG ((LM_DEBUG, "%s = %d\n", "error", result.error ()));
+ ACE_DEBUG ((LM_DEBUG, "********************\n"));
+#if 0
+ // This can overrun the ACE_Log_Msg buffer and do bad things.
+ // Re-enable it at your risk.
+ ACE_DEBUG ((LM_DEBUG, "%s = %s\n", "message_block", result.message_block ().rd_ptr ()));
+#endif /* 0 */
+
+ if (result.success () && result.bytes_transferred () != 0)
+ {
+ // Successful read: write the data to the file asynchronously.
+ // Note how we reuse the <ACE_Message_Block> for the writing.
+ // Therefore, we do not delete this buffer because it is handled
+ // in <handle_write_stream>.
+ if (this->wf_.write (result.message_block (),
+ result.bytes_transferred (),
+ this->file_offset_) == -1)
+ {
+ ACE_ERROR ((LM_ERROR,
+ "%p\n",
+ "ACE_Asynch_Write_File::write"));
+ return;
+ }
+
+ // Initiate new read from the stream.
+ if (this->initiate_read_stream () == -1)
+ return;
+ }
+ else
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ "Receiver completed\n"));
+
+ // No need for this message block anymore.
+ result.message_block ().release ();
+
+ // Note that we are done with the test.
+ done = 1;
+
+ // We are done: commit suicide.
+ delete this;
+ }
+}
+
+void
+Receiver::handle_write_file (const ACE_Asynch_Write_File::Result &result)
+{
+ ACE_DEBUG ((LM_DEBUG, "handle_write_file called\n"));
+
+ ACE_DEBUG ((LM_DEBUG, "********************\n"));
+ ACE_DEBUG ((LM_DEBUG, "%s = %d\n", "bytes_to_write", result.bytes_to_write ()));
+ ACE_DEBUG ((LM_DEBUG, "%s = %d\n", "handle", result.handle ()));
+ ACE_DEBUG ((LM_DEBUG, "%s = %d\n", "bytes_transfered", result.bytes_transferred ()));
+ ACE_DEBUG ((LM_DEBUG, "%s = %d\n", "act", (u_long) result.act ()));
+ ACE_DEBUG ((LM_DEBUG, "%s = %d\n", "success", result.success ()));
+ ACE_DEBUG ((LM_DEBUG, "%s = %d\n", "completion_key", (u_long) result.completion_key ()));
+ ACE_DEBUG ((LM_DEBUG, "%s = %d\n", "error", result.error ()));
+ ACE_DEBUG ((LM_DEBUG, "********************\n"));
+
+ result.message_block ().release ();
+
+ if (result.success ())
+ // Write successful: Increment file offset
+ this->file_offset_ += result.bytes_transferred ();
+
+ // This code is not robust enough to deal with short file writes
+ // (which hardly ever happen) ;-)
+ ACE_ASSERT (result.bytes_to_write () == result.bytes_transferred ());
+}
+
+class Sender : public ACE_Handler
+{
+ // = TITLE
+ // The class will be created by <main>. After connecting to the
+ // host, this class will then read data from a file and send it
+ // to the network connection.
+public:
+ Sender (void);
+ ~Sender (void);
+ int open (const ACE_TCHAR *host,
+ u_short port);
+ ACE_HANDLE handle (void) const;
+ void handle (ACE_HANDLE);
+
+protected:
+ // These methods are called by the freamwork
+
+ virtual void handle_transmit_file (const ACE_Asynch_Transmit_File::Result &result);
+ // This is called when asynchronous transmit files complete
+ virtual void handle_write_stream (const ACE_Asynch_Write_Stream::Result &result);
+ // This is called when asynchronous writes from the socket complete
+ virtual void handle_read_file (const ACE_Asynch_Read_File::Result &result);
+ // This is called when asynchronous reads from the socket complete
+
+private:
+ int transmit_file (void);
+ // Transmit the entire file in one fell swoop.
+
+ int initiate_read_file (void);
+ // Initiate an asynchronous file read.
+
+ ACE_SOCK_Stream stream_;
+ // Network I/O handle
+
+ ACE_Asynch_Write_Stream ws_;
+ // ws (write stream): for writing to the socket
+
+ ACE_Asynch_Read_File rf_;
+ // rf (read file): for writing from the file
+
+ ACE_Asynch_Transmit_File tf_;
+ // Transmit file.
+
+ ACE_HANDLE input_file_;
+ // File to read from
+
+ u_long file_offset_;
+ // Current file offset
+
+ u_long file_size_;
+ // File size
+
+ ACE_Message_Block welcome_message_;
+ // Welcome message
+
+ ACE_Asynch_Transmit_File::Header_And_Trailer header_and_trailer_;
+ // Header and trailer which goes with transmit_file
+
+ int stream_write_done_;
+ int transmit_file_done_;
+ // These flags help to determine when to close down the event loop
+};
+
+Sender::Sender (void)
+ : input_file_ (ACE_INVALID_HANDLE),
+ file_offset_ (0),
+ file_size_ (0),
+ stream_write_done_ (0),
+ transmit_file_done_ (0)
+{
+ // Moment of inspiration... :-)
+ static const char *data = "Welcome to Irfan World! Irfan RULES here !!\n";
+ this->welcome_message_.init (data,
+ ACE_OS::strlen (data));
+ this->welcome_message_.wr_ptr (ACE_OS::strlen (data));
+}
+
+Sender::~Sender (void)
+{
+ this->stream_.close ();
+}
+
+ACE_HANDLE
+Sender::handle (void) const
+{
+ return this->stream_.get_handle ();
+}
+
+void
+Sender::handle (ACE_HANDLE handle)
+{
+ this->stream_.set_handle (handle);
+}
+
+int
+Sender::open (const ACE_TCHAR *host,
+ u_short port)
+{
+ // Initialize stuff
+
+ // Open input file (in OVERLAPPED mode)
+ this->input_file_ =
+ ACE_OS::open (file, GENERIC_READ | FILE_FLAG_OVERLAPPED);
+ if (this->input_file_ == ACE_INVALID_HANDLE)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%p\n",
+ "ACE_OS::open"), -1);
+
+ // Find file size
+ this->file_size_ =
+ ACE_OS::filesize (this->input_file_);
+
+ // Connect to remote host
+ ACE_INET_Addr address (port, host);
+ ACE_SOCK_Connector connector;
+ if (connector.connect (this->stream_,
+ address) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%p\n",
+ "ACE_SOCK_Connector::connect"),
+ -1);
+
+ // Open ACE_Asynch_Write_Stream
+ if (this->ws_.open (*this) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%p\n",
+ "ACE_Asynch_Write_Stream::open"),
+ -1);
+
+ // Open ACE_Asynch_Read_File
+ if (this->rf_.open (*this, this->input_file_) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%p\n",
+ "ACE_Asynch_Read_File::open"),
+ -1);
+
+ // Start an asynchronous transmit file
+ if (this->transmit_file () == -1)
+ return -1;
+
+ // Start an asynchronous read file
+ if (this->initiate_read_file () == -1)
+ return -1;
+
+ return 0;
+}
+
+int
+Sender::transmit_file (void)
+{
+ // Open file (in SEQUENTIAL_SCAN mode)
+ ACE_HANDLE file_handle =
+ ACE_OS::open (file, GENERIC_READ | FILE_FLAG_SEQUENTIAL_SCAN);
+ if (file_handle == ACE_INVALID_HANDLE)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%p\n",
+ "ACE_OS::open"),
+ -1);
+
+ // Open ACE_Asynch_Transmit_File
+ if (this->tf_.open (*this) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%p\n",
+ "ACE_Asynch_Transmit_File::open"),
+ -1);
+
+ // Header and trailer data for the file.
+ // @@ What happens if header and trailer are the same?
+ this->header_and_trailer_.header_and_trailer (&this->welcome_message_,
+ this->welcome_message_.length (),
+ &this->welcome_message_,
+ this->welcome_message_.length ());
+
+ // Send the entire file in one fell swoop!
+ if (this->tf_.transmit_file (file_handle,
+ &this->header_and_trailer_) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%p\n",
+ "ACE_Asynch_Transmit_File::transmit_file"),
+ -1);
+
+ return 0;
+}
+
+void
+Sender::handle_transmit_file (const ACE_Asynch_Transmit_File::Result &result)
+{
+ ACE_DEBUG ((LM_DEBUG,
+ "handle_transmit_file called\n"));
+
+ ACE_DEBUG ((LM_DEBUG, "********************\n"));
+ ACE_DEBUG ((LM_DEBUG, "%s = %d\n", "socket", result.socket ()));
+ ACE_DEBUG ((LM_DEBUG, "%s = %d\n", "file", result.file ()));
+ ACE_DEBUG ((LM_DEBUG, "%s = %d\n", "bytes_to_write", result.bytes_to_write ()));
+ ACE_DEBUG ((LM_DEBUG, "%s = %d\n", "bytes_per_send", result.bytes_per_send ()));
+ ACE_DEBUG ((LM_DEBUG, "%s = %d\n", "flags", result.flags ()));
+ ACE_DEBUG ((LM_DEBUG, "%s = %d\n", "bytes_transfered", result.bytes_transferred ()));
+ ACE_DEBUG ((LM_DEBUG, "%s = %d\n", "act", (u_long) result.act ()));
+ ACE_DEBUG ((LM_DEBUG, "%s = %d\n", "success", result.success ()));
+ ACE_DEBUG ((LM_DEBUG, "%s = %d\n", "completion_key", (u_long) result.completion_key ()));
+ ACE_DEBUG ((LM_DEBUG, "%s = %d\n", "error", result.error ()));
+ ACE_DEBUG ((LM_DEBUG, "********************\n"));
+
+ // Done with file
+ ACE_OS::close (result.file ());
+
+ this->transmit_file_done_ = 1;
+ if (this->stream_write_done_)
+ done = 1;
+}
+
+int
+Sender::initiate_read_file (void)
+{
+ // Create a new <Message_Block>. Note that this message block will
+ // be used both to <read> data asynchronously from the file and to
+ // <write> data asynchronously to the socket.
+ ACE_Message_Block *mb = 0;
+ ACE_NEW_RETURN (mb,
+ ACE_Message_Block (BUFSIZ + 1),
+ -1);
+
+ // Inititiate an asynchronous read from the file
+ if (this->rf_.read (*mb,
+ mb->size () - 1,
+ this->file_offset_) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%p\n",
+ "ACE_Asynch_Read_File::read"),
+ -1);
+ return 0;
+}
+
+void
+Sender::handle_read_file (const ACE_Asynch_Read_File::Result &result)
+{
+ ACE_DEBUG ((LM_DEBUG,
+ "handle_read_file called\n"));
+
+ result.message_block ().rd_ptr ()[result.bytes_transferred ()] = '\0';
+
+ ACE_DEBUG ((LM_DEBUG, "********************\n"));
+ ACE_DEBUG ((LM_DEBUG, "%s = %d\n", "bytes_to_read", result.bytes_to_read ()));
+ ACE_DEBUG ((LM_DEBUG, "%s = %d\n", "handle", result.handle ()));
+ ACE_DEBUG ((LM_DEBUG, "%s = %d\n", "bytes_transfered", result.bytes_transferred ()));
+ ACE_DEBUG ((LM_DEBUG, "%s = %d\n", "act", (u_long) result.act ()));
+ ACE_DEBUG ((LM_DEBUG, "%s = %d\n", "success", result.success ()));
+ ACE_DEBUG ((LM_DEBUG, "%s = %d\n", "completion_key", (u_long) result.completion_key ()));
+ ACE_DEBUG ((LM_DEBUG, "%s = %d\n", "error", result.error ()));
+ ACE_DEBUG ((LM_DEBUG, "********************\n"));
+ //ACE_DEBUG ((LM_DEBUG, "%s = %s\n", "message_block", result.message_block ().rd_ptr ()));
+
+ if (result.success ())
+ {
+ // Read successful: increment offset and write data to network.
+ // Note how we reuse the <ACE_Message_Block> for the writing.
+ // Therefore, we do not delete this buffer because it is handled
+ // in <handle_write_stream>.
+
+ this->file_offset_ += result.bytes_transferred ();
+ if (this->ws_.write (result.message_block (),
+ result.bytes_transferred ()) == -1)
+ {
+ ACE_ERROR ((LM_ERROR,
+ "%p\n",
+ "ACE_Asynch_Write_Stream::write"));
+ return;
+ }
+
+ if (this->file_size_ > this->file_offset_)
+ {
+ // Start an asynchronous read file.
+ if (initiate_read_file () == -1)
+ return;
+ }
+ }
+}
+
+void
+Sender::handle_write_stream (const ACE_Asynch_Write_Stream::Result &result)
+{
+ ACE_DEBUG ((LM_DEBUG,
+ "handle_write_stream called\n"));
+
+ // Reset pointers.
+ result.message_block ().rd_ptr (result.message_block ().rd_ptr () - result.bytes_transferred ());
+
+ ACE_DEBUG ((LM_DEBUG, "********************\n"));
+ ACE_DEBUG ((LM_DEBUG, "%s = %d\n", "bytes_to_write", result.bytes_to_write ()));
+ ACE_DEBUG ((LM_DEBUG, "%s = %d\n", "handle", result.handle ()));
+ ACE_DEBUG ((LM_DEBUG, "%s = %d\n", "bytes_transfered", result.bytes_transferred ()));
+ ACE_DEBUG ((LM_DEBUG, "%s = %d\n", "act", (u_long) result.act ()));
+ ACE_DEBUG ((LM_DEBUG, "%s = %d\n", "success", result.success ()));
+ ACE_DEBUG ((LM_DEBUG, "%s = %d\n", "completion_key", (u_long) result.completion_key ()));
+ ACE_DEBUG ((LM_DEBUG, "%s = %d\n", "error", result.error ()));
+ ACE_DEBUG ((LM_DEBUG, "********************\n"));
+#if 0
+ ACE_DEBUG ((LM_DEBUG, "%s = %s\n", "message_block", result.message_block ().rd_ptr ()));
+#endif
+
+ if (result.success ())
+ {
+ // Partial write to socket
+ int unsent_data = result.bytes_to_write () - result.bytes_transferred ();
+ if (unsent_data != 0)
+ {
+ // Reset pointers
+ result.message_block ().rd_ptr (result.bytes_transferred ());
+
+ // Duplicate the message block and retry remaining data
+ if (this->ws_.write (*result.message_block ().duplicate (),
+ unsent_data) == -1)
+ {
+ ACE_ERROR ((LM_ERROR,
+ "%p\n",
+ "ACE_Asynch_Write_Stream::write"));
+ return;
+ }
+ }
+ else if (!(this->file_size_ > this->file_offset_))
+ {
+ this->stream_write_done_ = 1;
+ if (this->transmit_file_done_)
+ done = 1;
+ }
+ }
+
+ // Release message block.
+ result.message_block ().release ();
+}
+
+static int
+parse_args (int argc, ACE_TCHAR *argv[])
+{
+ ACE_Get_Opt get_opt (argc, argv, ACE_TEXT("h:p:f:d:"));
+ int c;
+
+ while ((c = get_opt ()) != EOF)
+ switch (c)
+ {
+ case 'h':
+ host = get_opt.opt_arg ();
+ break;
+ case 'p':
+ port = ACE_OS::atoi (get_opt.opt_arg ());
+ break;
+ case 'f':
+ file = get_opt.opt_arg ();
+ break;
+ case 'd':
+ dump_file = get_opt.opt_arg ();
+ break;
+ default:
+ ACE_ERROR ((LM_ERROR, "%p.\n",
+ "usage :\n"
+ "-h <host>\n"
+ "-p <port>\n"
+ "-f <file>\n"));
+ return -1;
+ }
+
+ return 0;
+}
+
+int
+ACE_TMAIN (int argc, ACE_TCHAR *argv[])
+{
+ if (parse_args (argc, argv) == -1)
+ return -1;
+
+ Sender sender;
+
+ // Note: acceptor parameterized by the Receiver.
+ ACE_Asynch_Acceptor<Receiver> acceptor;
+
+ // If passive side
+ if (host == 0)
+ {
+ if (acceptor.open (ACE_INET_Addr (port),
+ initial_read_size,
+ 1) == -1)
+ return -1;
+ }
+ // If active side
+ else if (sender.open (host, port) == -1)
+ return -1;
+
+ int success = 1;
+
+ while (success > 0 && !done)
+ // Dispatch events via Proactor singleton.
+ success = ACE_Proactor::instance ()->handle_events ();
+
+ return 0;
+}
+
+#else /* ACE_WIN32 && !ACE_HAS_WINCE || ACE_HAS_AIO_CALLS*/
+
+int
+ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ ACE_DEBUG ((LM_DEBUG,
+ "This example does not work on this platform.\n"));
+ return 1;
+}
+
+#endif /* ACE_WIN32 && !ACE_HAS_WINCE || ACE_HAS_AIO_CALLS*/
diff --git a/ACE/examples/Reactor/Proactor/test_proactor.h b/ACE/examples/Reactor/Proactor/test_proactor.h
new file mode 100644
index 00000000000..482e176041e
--- /dev/null
+++ b/ACE/examples/Reactor/Proactor/test_proactor.h
@@ -0,0 +1,56 @@
+/*
+** $Id$
+*/
+
+#ifndef _TEST_PROACTOR_H
+#define _TEST_PROACTOR_H
+
+#include "ace/Asynch_IO.h"
+
+class Receiver : public ACE_Service_Handler
+{
+ // = TITLE
+ // The class will be created by <ACE_Asynch_Acceptor> when new
+ // connections arrive. This class will then receive data from
+ // the network connection and dump it to a file.
+public:
+ // = Initialization and termination.
+ Receiver (void);
+ ~Receiver (void);
+
+ virtual void open (ACE_HANDLE handle,
+ ACE_Message_Block &message_block);
+ // This is called after the new connection has been accepted.
+
+protected:
+ // These methods are called by the framework
+
+ virtual void handle_read_stream (const ACE_Asynch_Read_Stream::Result &result);
+ // This is called when asynchronous <read> operation from the socket
+ // complete.
+
+ virtual void handle_write_file (const ACE_Asynch_Write_File::Result &result);
+ // This is called when an asynchronous <write> to the file
+ // completes.
+
+private:
+ int initiate_read_stream (void);
+ // Initiate an asynchronous <read> operation on the socket.
+
+ ACE_Asynch_Read_Stream rs_;
+ // rs (read stream): for reading from a socket.
+
+ ACE_HANDLE dump_file_;
+ // File for dumping data.
+
+ ACE_Asynch_Write_File wf_;
+ // wf (write file): for writing to a file.
+
+ u_long file_offset_;
+ // Offset for the file.
+
+ ACE_HANDLE handle_;
+ // Handle for IO to remote peer.
+};
+
+#endif /* _TEST_PROACTOR_H */
diff --git a/ACE/examples/Reactor/Proactor/test_proactor2.cpp b/ACE/examples/Reactor/Proactor/test_proactor2.cpp
new file mode 100644
index 00000000000..cd5cbf7092e
--- /dev/null
+++ b/ACE/examples/Reactor/Proactor/test_proactor2.cpp
@@ -0,0 +1,808 @@
+// $Id$
+
+// ============================================================================
+//
+// = LIBRARY
+// examples
+//
+// = FILENAME
+// test_proactor2.cpp
+//
+// = DESCRIPTION
+// Alexander Libman <Alibman@baltimore.com> modified
+// <test_proactor> and made this test. Instead of writing received
+// data to the file, the receiver sends them back to the
+// sender,i.e. ACE_Asynch_Write_File wf_ has been changed to
+// ACE_Asynch_Write_Stream wf_.
+//
+// = AUTHOR
+// Irfan Pyarali <irfan@cs.wustl.edu> and Alexander Libman
+// <Alibman@baltimore.com>.
+// ============================================================================
+
+#include "ace/Signal.h"
+
+#include "ace/Service_Config.h"
+#include "ace/Proactor.h"
+#include "ace/Asynch_IO.h"
+#include "ace/Asynch_IO_Impl.h"
+#include "ace/Asynch_Acceptor.h"
+#include "ace/INET_Addr.h"
+#include "ace/SOCK_Connector.h"
+#include "ace/SOCK_Acceptor.h"
+#include "ace/SOCK_Stream.h"
+#include "ace/Message_Block.h"
+#include "ace/Get_Opt.h"
+
+// FUZZ: disable check_for_streams_include
+#include "ace/streams.h"
+
+#include "ace/Task.h"
+#include "ace/OS_main.h"
+
+ACE_RCSID(Proactor, test_proactor2, "test_proactor2.cpp,v 1.27 2000/03/07 17:15:56 schmidt Exp")
+
+#if ((defined (ACE_WIN32) && !defined (ACE_HAS_WINCE)) || (defined (ACE_HAS_AIO_CALLS)))
+ // This only works on Win32 platforms and on Unix platforms supporting
+ // POSIX aio calls.
+
+#if defined (ACE_WIN32) && !defined (ACE_HAS_WINCE)
+
+#include "ace/WIN32_Proactor.h"
+
+#elif defined (ACE_HAS_AIO_CALLS)
+
+#include "ace/POSIX_Proactor.h"
+
+#endif
+
+ // Some debug helper functions
+ int DisableSignal ( int SigNum );
+int PrintSigMask ();
+
+#define COUT(X) cout << X ; cout.flush ();
+
+// Host that we're connecting to.
+static ACE_TCHAR *host = 0;
+
+// duplex mode: ==0 half-duplex
+// !=0 full duplex
+static int duplex = 0 ;
+
+// number threads in the Proactor thread pool
+static int nThreads = 1;
+
+// Port that we're receiving connections on.
+static u_short port = ACE_DEFAULT_SERVER_PORT;
+
+// Size of each initial asynchronous <read> operation.
+static int initial_read_size = BUFSIZ;
+
+
+#define MyMutex ACE_Recursive_Thread_Mutex
+//#define MyMutex ACE_Thread_Mutex
+//#define MyMutex ACE_Null_Mutex
+
+//--------------------------------------------------------------------------
+// MyTask plays role for Proactor threads pool
+//--------------------------------------------------------------------------
+class MyTask: public ACE_Task<ACE_MT_SYNCH>
+{
+
+public:
+
+ int svc (void) ;
+};
+
+
+int MyTask::svc (void )
+{
+ ACE_DEBUG ((LM_DEBUG, "(%t) MyTask started\n"));
+
+ while ( ACE_Proactor::event_loop_done () == 0 )
+ {
+ ACE_Proactor::run_event_loop ();
+ }
+
+ ACE_DEBUG ((LM_DEBUG, "(%t) MyTask finished\n"));
+ return 0 ;
+}
+
+//-----------------------------------------------------------
+// Receiver
+//-----------------------------------------------------------
+class Receiver : public ACE_Service_Handler
+{
+public:
+
+ Receiver (void);
+ ~Receiver (void);
+
+ virtual void open (ACE_HANDLE handle,
+ ACE_Message_Block &message_block);
+ // This is called after the new connection has been accepted.
+
+protected:
+ // These methods are called by the framework
+
+ virtual void handle_read_stream (const ACE_Asynch_Read_Stream::Result
+ &result);
+ // This is called when asynchronous <read> operation from the socket
+ // complete.
+
+ virtual void handle_write_stream (const ACE_Asynch_Write_Stream::Result
+ &result);
+ // This is called when an asynchronous <write> to the file
+ // completes.
+
+private:
+ int initiate_read_stream (void);
+ int initiate_write_stream (ACE_Message_Block & mb, int nBytes );
+ bool check_destroy () ;
+
+ ACE_Asynch_Read_Stream rs_;
+ ACE_Asynch_Write_Stream ws_;
+ ACE_HANDLE handle_;
+ MyMutex m_Mtx ;
+ long nIOCount ;
+ static long nSessions ;
+};
+
+
+long Receiver::nSessions = 0 ;
+
+Receiver::Receiver (void)
+ : handle_ (ACE_INVALID_HANDLE),
+ nIOCount ( 0 )
+{
+ ACE_Guard<MyMutex> locker (m_Mtx) ;
+ nSessions ++ ;
+ ACE_DEBUG ((LM_DEBUG, "Receiver Ctor nSessions=%d\n", nSessions ));
+}
+
+Receiver::~Receiver (void)
+{
+ ACE_Guard<MyMutex> locker (m_Mtx) ;
+ nSessions -- ;
+ ACE_OS::closesocket (this->handle_);
+ ACE_DEBUG ((LM_DEBUG, "~Receiver Dtor nSessions=%d\n", nSessions ));
+}
+
+//---------------------------------------------------------------------
+// return true if we alive, false we commited suicide
+//
+//---------------------------------------------------------------------
+bool Receiver::check_destroy ()
+{
+ {
+ ACE_Guard<MyMutex> locker (m_Mtx) ;
+
+ if ( nIOCount > 0 )
+ {
+ return true ;
+ }
+ }
+
+ delete this ;
+ return false ;
+}
+
+
+void Receiver::open (ACE_HANDLE handle,
+ ACE_Message_Block &message_block)
+{
+ ACE_UNUSED_ARG (message_block);
+
+ ACE_DEBUG ((LM_DEBUG,
+ "%N:%l:Receiver::open called\n"));
+
+
+ this->handle_ = handle;
+
+ if (this->ws_.open (*this, this->handle_ ) == -1)
+ {
+ ACE_ERROR ((LM_ERROR,
+ "%p\n",
+ "ACE_Asynch_Write_Stream::open"));
+
+ }
+ else if (this->rs_.open (*this, this->handle_) == -1)
+ {
+ ACE_ERROR ((LM_ERROR,
+ "%p\n",
+ "ACE_Asynch_Read_Stream::open"));
+ }
+ else
+ {
+ initiate_read_stream ();
+ }
+
+
+ check_destroy ();
+}
+
+int Receiver::initiate_read_stream (void)
+{
+ ACE_Guard<MyMutex> locker (m_Mtx) ;
+
+ // Create a new <Message_Block>. Note that this message block will
+ // be used both to <read> data asynchronously from the socket and to
+ // <write> data asynchronously to the file.
+ ACE_DEBUG ((LM_DEBUG,
+ "initiate_read_stream called\n"));
+
+
+ ACE_Message_Block *mb = 0;
+ ACE_NEW_RETURN (mb,
+ ACE_Message_Block (BUFSIZ + 1),
+ -1);
+
+ // Inititiate read
+ if (this->rs_.read (*mb, mb->size ()- 1) == -1)
+ {
+ mb->release () ;
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%p\n",
+ "ACE_Asynch_Read_Stream::read"),
+ -1);
+ }
+
+ nIOCount++ ;
+ return 0;
+}
+
+int Receiver::initiate_write_stream (ACE_Message_Block & mb, int nBytes )
+{
+ ACE_Guard<MyMutex> locker (m_Mtx) ;
+ if (this->ws_.write (mb , nBytes ) == -1)
+ {
+ mb.release ();
+ ACE_ERROR_RETURN((LM_ERROR,
+ "%p\n",
+ "ACE_Asynch_Write_File::write"),
+ -1);
+ }
+
+ nIOCount++ ;
+ return 0;
+}
+
+void
+Receiver::handle_read_stream (const ACE_Asynch_Read_Stream::Result &result)
+{
+ ACE_DEBUG ((LM_DEBUG,
+ "handle_read_stream called\n"));
+
+ // Reset pointers.
+ result.message_block ().rd_ptr ()[result.bytes_transferred ()] =
+ '\0';
+
+ ACE_DEBUG ((LM_DEBUG, "********************\n"));
+ ACE_DEBUG ((LM_DEBUG, "%s = %d\n", "bytes_to_read", result.bytes_to_read
+ ()));
+ ACE_DEBUG ((LM_DEBUG, "%s = %d\n", "handle", result.handle ()));
+ ACE_DEBUG ((LM_DEBUG, "%s = %d\n", "bytes_transfered",
+ result.bytes_transferred ()));
+ ACE_DEBUG ((LM_DEBUG, "%s = %d\n", "act", (u_long) result.act ()));
+ ACE_DEBUG ((LM_DEBUG, "%s = %d\n", "success", result.success ()));
+ ACE_DEBUG ((LM_DEBUG, "%s = %d\n", "completion_key", (u_long)
+ result.completion_key ()));
+ ACE_DEBUG ((LM_DEBUG, "%s = %d\n", "error", result.error ()));
+ ACE_DEBUG ((LM_DEBUG, "********************\n"));
+ ACE_DEBUG ((LM_DEBUG, "%s = %s\n", "message_block",
+ result.message_block ().rd_ptr ()));
+
+ if ( result.success () && result.bytes_transferred () != 0)
+ {
+ // Successful read: write the data to the file asynchronously.
+ // Note how we reuse the <ACE_Message_Block> for the writing.
+ // Therefore, we do not delete this buffer because it is handled
+ // in <handle_write_stream>.
+
+ if(this->initiate_write_stream (result.message_block (),
+
+ result.bytes_transferred () ) == 0 )
+ {
+ if ( duplex != 0 )
+ {
+ // Initiate new read from the stream.
+ this->initiate_read_stream () ;
+ }
+ }
+ }
+ else
+ {
+ result.message_block ().release ();
+ ACE_DEBUG ((LM_DEBUG, "Receiver completed\n"));
+ }
+
+ {
+ ACE_Guard<MyMutex> locker (m_Mtx) ;
+ nIOCount-- ;
+ }
+ check_destroy () ;
+}
+
+void
+Receiver::handle_write_stream (const ACE_Asynch_Write_Stream::Result
+ &result)
+{
+ ACE_DEBUG ((LM_DEBUG, "handle_write_stream called\n"));
+
+ ACE_DEBUG ((LM_DEBUG, "********************\n"));
+ ACE_DEBUG ((LM_DEBUG, "%s = %d\n", "bytes_to_write",
+ result.bytes_to_write ()));
+ ACE_DEBUG ((LM_DEBUG, "%s = %d\n", "handle", result.handle ()));
+ ACE_DEBUG ((LM_DEBUG, "%s = %d\n", "bytes_transfered",
+ result.bytes_transferred ()));
+ ACE_DEBUG ((LM_DEBUG, "%s = %d\n", "act", (u_long) result.act ()));
+ ACE_DEBUG ((LM_DEBUG, "%s = %d\n", "success", result.success ()));
+ ACE_DEBUG ((LM_DEBUG, "%s = %d\n", "completion_key", (u_long)
+ result.completion_key ()));
+ ACE_DEBUG ((LM_DEBUG, "%s = %d\n", "error", result.error ()));
+ ACE_DEBUG ((LM_DEBUG, "********************\n"));
+
+ result.message_block ().release ();
+
+ if (result.success ())
+ {
+ // This code is not robust enough to deal with short file writes
+ // (which hardly ever happen) ;-)
+ //ACE_ASSERT (result.bytes_to_write () == result.bytes_transferred ());
+
+ if ( duplex == 0 )
+ {
+ initiate_read_stream () ;
+ }
+ }
+
+ {
+ ACE_Guard<MyMutex> locker (m_Mtx) ;
+ nIOCount-- ;
+ }
+ check_destroy () ;
+}
+
+//-------------------------------------------------------------------------
+// Sender: sends indefinetely welcome message
+// and recieves it back
+//------------------------------------------------------------------------
+class Sender : public ACE_Handler
+{
+public:
+ Sender (void);
+ ~Sender (void);
+ int open (const ACE_TCHAR *host, u_short port);
+ void close ();
+ ACE_HANDLE handle (void) const;
+ void handle (ACE_HANDLE);
+
+protected:
+// These methods are called by the freamwork
+
+virtual void handle_read_stream (const ACE_Asynch_Read_Stream::Result
+&result);
+// This is called when asynchronous reads from the socket complete
+
+virtual void handle_write_stream (const ACE_Asynch_Write_Stream::Result
+&result);
+// This is called when asynchronous writes from the socket complete
+
+private:
+
+int initiate_read_stream (void);
+int initiate_write_stream (void);
+
+ACE_SOCK_Stream stream_;
+// Network I/O handle
+
+ACE_Asynch_Write_Stream ws_;
+// ws (write stream): for writing to the socket
+
+ACE_Asynch_Read_Stream rs_;
+// rs (read file): for reading from the socket
+
+ACE_Message_Block welcome_message_;
+// Welcome message
+
+MyMutex m_Mtx ;
+long nIOCount ;
+};
+
+static char *data = "Welcome to Irfan World! Irfan RULES here !!\n";
+
+Sender::Sender (void)
+ :nIOCount ( 0 )
+{
+ // Moment of inspiration... :-)
+ this->welcome_message_.init (data, ACE_OS::strlen (data));
+}
+
+Sender::~Sender (void)
+{
+ close ();
+}
+
+void Sender::close ()
+{
+ this->stream_.close ();
+}
+
+ACE_HANDLE Sender::handle (void) const
+{
+ return this->stream_.get_handle ();
+}
+
+void Sender::handle (ACE_HANDLE handle)
+{
+ this->stream_.set_handle (handle);
+}
+
+int Sender::open (const ACE_TCHAR *host, u_short port)
+{
+ // Initialize stuff
+ // Connect to remote host
+ ACE_INET_Addr address (port, host);
+ ACE_SOCK_Connector connector;
+
+ if (connector.connect (this->stream_,
+ address) == -1)
+ {
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%p\n",
+ "ACE_SOCK_Connector::connect"),
+ -1);
+ }
+
+ // Open ACE_Asynch_Write_Stream
+ if (this->ws_.open (*this) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%p\n",
+ "ACE_Asynch_Write_Stream::open"),
+ -1);
+
+ // Open ACE_Asynch_Read_Stream
+ if (this->rs_.open (*this) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%p\n",
+ "ACE_Asynch_Read_File::open"),
+ -1);
+
+ // Start an asynchronous transmit file
+ if ( this->initiate_write_stream () == -1)
+ return -1;
+
+ if ( duplex != 0 )
+ {
+ // Start an asynchronous read file
+ if (this->initiate_read_stream () == -1)
+ return -1;
+ }
+
+ return 0;
+}
+
+int Sender::initiate_write_stream (void)
+{
+ ACE_Guard<MyMutex> locker (m_Mtx) ;
+
+
+ welcome_message_.rd_ptr( welcome_message_.base ());
+ welcome_message_.wr_ptr( welcome_message_.base ());
+ welcome_message_.wr_ptr (ACE_OS::strlen (data));
+
+ if (this->ws_.write (welcome_message_,
+ welcome_message_.length ()
+ ) == -1)
+ {
+ ACE_ERROR_RETURN((LM_ERROR,
+ "%p\n",
+ "ACE_Asynch_Write_File::write"),
+ -1);
+ }
+
+ nIOCount++ ;
+ return 0;
+}
+
+int Sender::initiate_read_stream (void)
+{
+ ACE_Guard<MyMutex> locker (m_Mtx) ;
+
+ // Create a new <Message_Block>. Note that this message block will
+ // be used both to <read> data asynchronously from the socket and to
+ // <write> data asynchronously to the file.
+ ACE_DEBUG ((LM_DEBUG,
+ "initiate_read_stream called\n"));
+
+
+ ACE_Message_Block *mb = 0;
+ ACE_NEW_RETURN (mb,
+ ACE_Message_Block (BUFSIZ + 1),
+ -1);
+
+ // Inititiate read
+ if (this->rs_.read (*mb, mb->size ()- 1) == -1)
+ {
+ mb->release () ;
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%p\n",
+ "ACE_Asynch_Read_Stream::read"),
+ -1);
+ }
+
+ nIOCount++ ;
+ return 0;
+}
+
+
+void Sender::handle_write_stream (const ACE_Asynch_Write_Stream::Result
+ &result)
+{
+ ACE_DEBUG ((LM_DEBUG,
+ "handle_write_stream called\n"));
+
+ // Reset pointers.
+ result.message_block ().rd_ptr (result.message_block ().rd_ptr () -
+ result.bytes_transferred ());
+
+
+ ACE_DEBUG ((LM_DEBUG, "********************\n"));
+ ACE_DEBUG ((LM_DEBUG, "%s = %d\n", "bytes_to_write",
+ result.bytes_to_write ()));
+ ACE_DEBUG ((LM_DEBUG, "%s = %d\n", "handle", result.handle ()));
+ ACE_DEBUG ((LM_DEBUG, "%s = %d\n", "bytes_transfered",
+ result.bytes_transferred ()));
+ ACE_DEBUG ((LM_DEBUG, "%s = %d\n", "act", (u_long) result.act ()));
+ ACE_DEBUG ((LM_DEBUG, "%s = %d\n", "success", result.success ()));
+ ACE_DEBUG ((LM_DEBUG, "%s = %d\n", "completion_key", (u_long)
+ result.completion_key ()));
+ ACE_DEBUG ((LM_DEBUG, "%s = %d\n", "error", result.error ()));
+ ACE_DEBUG ((LM_DEBUG, "********************\n"));
+ ACE_DEBUG ((LM_DEBUG, "%s = %s\n", "message_block",
+ result.message_block ().rd_ptr ()));
+
+ // Simplify just for Test
+ if (result.success () && result.bytes_transferred () != 0)
+ {
+ if ( duplex != 0 ) // full duplex, continue write
+ {
+ initiate_write_stream () ;
+ }
+ else // half-duplex read reply, after read we will start
+ // write
+ {
+ initiate_read_stream () ;
+ }
+ }
+
+ {
+ ACE_Guard<MyMutex> locker (m_Mtx) ;
+ nIOCount-- ;
+ }
+}
+
+void
+Sender::handle_read_stream (const ACE_Asynch_Read_Stream::Result &result)
+{
+ ACE_DEBUG ((LM_DEBUG,
+ "handle_read_stream called\n"));
+
+ // Reset pointers.
+ result.message_block ().rd_ptr ()[result.bytes_transferred ()] =
+ '\0';
+
+ ACE_DEBUG ((LM_DEBUG, "********************\n"));
+ ACE_DEBUG ((LM_DEBUG, "%s = %d\n", "bytes_to_read", result.bytes_to_read
+ ()));
+ ACE_DEBUG ((LM_DEBUG, "%s = %d\n", "handle", result.handle ()));
+ ACE_DEBUG ((LM_DEBUG, "%s = %d\n", "bytes_transfered",
+ result.bytes_transferred ()));
+ ACE_DEBUG ((LM_DEBUG, "%s = %d\n", "act", (u_long) result.act ()));
+ ACE_DEBUG ((LM_DEBUG, "%s = %d\n", "success", result.success ()));
+ ACE_DEBUG ((LM_DEBUG, "%s = %d\n", "completion_key", (u_long)
+ result.completion_key ()));
+ ACE_DEBUG ((LM_DEBUG, "%s = %d\n", "error", result.error ()));
+ ACE_DEBUG ((LM_DEBUG, "********************\n"));
+ ACE_DEBUG ((LM_DEBUG, "%s = %s\n", "message_block",
+ result.message_block ().rd_ptr ()));
+
+ result.message_block().release ();
+
+ if ( result.success () && result.bytes_transferred () != 0)
+ {
+ // Successful read: write the data to the file asynchronously.
+ // Note how we reuse the <ACE_Message_Block> for the writing.
+ // Therefore, we do not delete this buffer because it is handled
+ // in <handle_write_stream>.
+
+ if ( duplex != 0 ) // full duplex, continue read
+ {
+ initiate_read_stream () ;
+ }
+ else // half-duplex writey, after write we will start read
+ {
+ initiate_write_stream () ;
+ }
+ }
+
+ {
+ ACE_Guard<MyMutex> locker (m_Mtx) ;
+ nIOCount-- ;
+ }
+}
+
+//--------------------------------------------------------------------------
+
+static int
+parse_args (int argc, ACE_TCHAR *argv[])
+{
+ ACE_Get_Opt get_opt (argc, argv, ACE_TEXT("n:p:d:h:"));
+ int c;
+
+ while ((c = get_opt ()) != EOF)
+ switch (c)
+ {
+ case 'h':
+ host = get_opt.opt_arg ();
+ break;
+ case 'n':
+ nThreads = ACE_OS::atoi (get_opt.opt_arg ()) ;
+ break;
+ case 'p':
+ port = ACE_OS::atoi (get_opt.opt_arg ());
+ break;
+ case 'd':
+ duplex = ACE_OS::atoi (get_opt.opt_arg ());
+ break;
+ default:
+ ACE_ERROR ((LM_ERROR, "%p.\n",
+ "usage :\n"
+ "-h <host> for Sender mode\n"
+ "-d <duplex mode 1-on/0-off>\n"
+ "-p <port to listen/connect>\n"
+ "-n <number threads for Proactor pool>\n"));
+ return -1;
+ }
+
+ return 0;
+}
+
+int
+ACE_TMAIN (int argc, ACE_TCHAR *argv[])
+{
+ ACE_UNUSED_ARG (initial_read_size);
+
+ if (parse_args (argc, argv) == -1)
+ return -1;
+
+#if defined (ACE_WIN32) && !defined (ACE_HAS_WINCE)
+
+ ACE_WIN32_Proactor * pImpl = new ACE_WIN32_Proactor;
+
+#elif defined (ACE_HAS_AIO_CALLS)
+
+ // ACE_POSIX_AIOCB_Proactor * pImpl = new ACE_POSIX_AIOCB_Proactor;
+ ACE_POSIX_SIG_Proactor * pImpl = new ACE_POSIX_SIG_Proactor;
+#endif
+
+ ACE_Proactor Proactor ( pImpl ,1 );
+
+ ACE_Proactor::instance( & Proactor );
+
+
+ MyTask Task1 ;
+
+ if (Task1.activate (THR_NEW_LWP, nThreads ) == -1)
+ {
+ ACE_ERROR_RETURN ((LM_ERROR, "%p.\n", "main"), -1);
+ }
+
+ Sender sender;
+ ACE_Asynch_Acceptor<Receiver> acceptor;
+
+ int Rc = -1 ;
+
+ if ( host == NULL ) // Acceptor
+ {
+ // Simplify , initial read with zero size
+ Rc = acceptor.open (ACE_INET_Addr (port),0,1);
+
+ }
+ else
+ {
+ Rc = sender.open (host, port);
+ }
+
+ if ( Rc == 0 )
+ {
+ char c ;
+ cout << "Press any key to stop and exit=>\n" << flush ;
+ cin.clear ();
+ cin >> c ;
+ }
+
+ ACE_Proactor::end_event_loop () ;
+
+ if ( host != NULL ) // we are sender
+ {
+ sender.close () ; // disconnect to get reciever error !!!
+ }
+
+
+ ACE_Thread_Manager * pTM = ACE_Thread_Manager::instance();
+
+ pTM->wait_task ( & Task1 ) ;
+
+ ACE_Proactor::instance( ( ACE_Proactor* )NULL );
+
+ return 0;
+}
+//--------------------------------------------------------------------
+//
+//--------------------------------------------------------------------
+int DisableSignal ( int SigNum )
+{
+
+#ifndef ACE_WIN32
+ sigset_t signal_set;
+ if ( sigemptyset (&signal_set) == - 1 )
+ {
+ ACE_ERROR ((LM_ERROR,
+ "Error:(%P | %t):%p\n",
+ "sigemptyset failed"));
+ }
+
+ sigaddset (&signal_set, SigNum);
+
+ // Put the <signal_set>.
+ if (ACE_OS::pthread_sigmask (SIG_BLOCK, &signal_set, 0) != 0)
+ {
+ ACE_ERROR ((LM_ERROR,
+ "Error:(%P | %t):%p\n",
+ "pthread_sigmask failed"));
+ }
+#else
+ ACE_UNUSED_ARG(SigNum);
+#endif
+
+ return 1;
+}
+//--------------------------------------------------------------------
+// Get the <signal_set> back from the OS.
+//--------------------------------------------------------------------
+
+int PrintSigMask ()
+{
+#ifndef ACE_WIN32
+
+ sigset_t mask ;
+ int member = 0;
+
+ COUT ( "\n=============Signal Mask==========" )
+
+ if (ACE_OS::pthread_sigmask (SIG_SETMASK, 0, & mask ) != 0)
+ {
+ ACE_ERROR ((LM_ERROR,
+ "Error:(%P | %t):%p\n",
+ "ACE_OS::pthread_sigmask failed"));
+ }
+ else for (int i = 1 ; i < 1000; i++)
+ {
+ member = sigismember (&mask,i);
+
+ COUT ( "\nSig " )
+ COUT ( i )
+ COUT ( " is " )
+ COUT (member )
+
+ if (member == -1)
+ {
+ break ;
+ }
+ }
+#endif
+ return 0;
+}
+
+#endif /* ACE_WIN32 && !ACE_HAS_WINCE || ACE_HAS_AIO_CALLS*/
diff --git a/ACE/examples/Reactor/Proactor/test_proactor3.cpp b/ACE/examples/Reactor/Proactor/test_proactor3.cpp
new file mode 100644
index 00000000000..c47468276c8
--- /dev/null
+++ b/ACE/examples/Reactor/Proactor/test_proactor3.cpp
@@ -0,0 +1,864 @@
+// $Id$
+
+// ============================================================================
+//
+// = LIBRARY
+// examples
+//
+// = FILENAME
+// test_proactor3.cpp
+//
+// = DESCRIPTION
+// This program illustrates how the <ACE_Proactor> can be used to
+// implement an application that does various asynchronous
+// operations.
+//
+// = AUTHOR
+// Irfan Pyarali <irfan@cs.wustl.edu>
+// modified by Alexander Libman <alibman@baltimore.com>
+// from original test_proactor.cpp
+// ============================================================================
+
+#include "ace/Signal.h"
+
+#include "ace/Service_Config.h"
+#include "ace/Proactor.h"
+#include "ace/Asynch_IO.h"
+#include "ace/Asynch_IO_Impl.h"
+#include "ace/Asynch_Acceptor.h"
+#include "ace/INET_Addr.h"
+#include "ace/SOCK_Connector.h"
+#include "ace/SOCK_Acceptor.h"
+#include "ace/SOCK_Stream.h"
+#include "ace/Message_Block.h"
+#include "ace/Get_Opt.h"
+
+// FUZZ: disable check_for_streams_include
+#include "ace/streams.h"
+
+#include "ace/Task.h"
+
+ACE_RCSID(Proactor, test_proactor, "test_proactor.cpp,v 1.27 2000/03/07 17:15:56 schmidt Exp")
+
+#if ((defined (ACE_WIN32) && !defined (ACE_HAS_WINCE)) || (defined (ACE_HAS_AIO_CALLS)))
+ // This only works on Win32 platforms and on Unix platforms
+ // supporting POSIX aio calls.
+
+#if defined (ACE_WIN32) && !defined (ACE_HAS_WINCE)
+
+# include "ace/WIN32_Proactor.h"
+
+#elif defined (ACE_HAS_AIO_CALLS)
+
+# include "ace/POSIX_Proactor.h"
+# include "ace/SUN_Proactor.h"
+
+#endif /* defined (ACE_WIN32) && !defined (ACE_HAS_WINCE) */
+
+// Some debug helper functions
+static int disable_signal (int sigmin, int sigmax);
+#if 0
+static int print_sigmask (void);
+#endif
+
+#define COUT(X) cout << X; cout.flush ();
+
+// Proactor Type (UNIX only, Win32 ignored) 0-default, 1 -AIOCB,
+// 2-SIG, 3-SUN
+static int proactor_type = 0;
+
+// POSIX : > 0 max number aio operations proactor,
+static int max_aio_operations = 0;
+
+// Host that we're connecting to.
+static ACE_TCHAR *host = 0;
+
+// number of Senders instances
+static int senders = 1;
+static const int MaxSenders = 100;
+
+// duplex mode: ==0 half-duplex
+// !=0 full duplex
+static int duplex = 0;
+
+// number threads in the Proactor thread pool
+static int threads = 1;
+
+// Port that we're receiving connections on.
+static u_short port = ACE_DEFAULT_SERVER_PORT;
+
+class MyTask: public ACE_Task<ACE_MT_SYNCH>
+{
+ // = TITLE
+ // MyTask plays role for Proactor threads pool
+public:
+ MyTask (void) : threads_ (0), proactor_ (0) {}
+
+ int svc (void);
+ void waitready (void) { event_.wait (); }
+
+private:
+ ACE_Recursive_Thread_Mutex mutex_;
+ int threads_;
+ ACE_Proactor *proactor_;
+ ACE_Manual_Event event_;
+
+ void create_proactor (void);
+ void delete_proactor (void);
+};
+
+void
+MyTask::create_proactor (void)
+{
+ ACE_Guard<ACE_Recursive_Thread_Mutex> locker (mutex_);
+
+ if (threads_ == 0)
+ {
+#if defined (ACE_WIN32) && !defined (ACE_HAS_WINCE)
+ ACE_WIN32_Proactor *proactor = new ACE_WIN32_Proactor;
+ ACE_DEBUG ((LM_DEBUG,"(%t) Create Proactor Type=WIN32"));
+
+#elif defined (ACE_HAS_AIO_CALLS)
+
+ ACE_POSIX_Proactor *proactor = 0;
+
+ switch (proactor_type)
+ {
+ case 1: proactor = new ACE_POSIX_AIOCB_Proactor (max_aio_operations);
+ ACE_DEBUG ((LM_DEBUG,"(%t) Create Proactor Type=AIOCB\n"));
+ break;
+ case 2: proactor = new ACE_POSIX_SIG_Proactor;
+ ACE_DEBUG ((LM_DEBUG,"(%t) Create Proactor Type=SIG\n"));
+ break;
+# if defined (sun)
+ case 3: proactor = new ACE_SUN_Proactor (max_aio_operations);
+ ACE_DEBUG ((LM_DEBUG,"(%t) Create Proactor Type=SUN\n"));
+ break;
+# endif /* sun */
+ default:proactor = new ACE_POSIX_SIG_Proactor;
+ ACE_DEBUG ((LM_DEBUG,"(%t) Create Proactor Type=SIG\n"));
+ break;
+ }
+#endif
+
+ proactor_ = new ACE_Proactor (proactor, 1);
+
+ ACE_Proactor::instance(proactor_);
+ event_.signal ();
+ }
+
+ threads_++;
+}
+
+void
+MyTask::delete_proactor (void)
+{
+ ACE_Guard<ACE_Recursive_Thread_Mutex> locker (mutex_);
+ if (--threads_ == 0)
+ {
+ ACE_DEBUG ((LM_DEBUG, "(%t) Delete Proactor\n"));
+ ACE_Proactor::instance ((ACE_Proactor *) 0);
+ delete proactor_;
+ proactor_ = 0;
+ }
+}
+
+int
+MyTask::svc (void)
+{
+ ACE_DEBUG ((LM_DEBUG, "(%t) MyTask started\n"));
+
+ create_proactor ();
+ disable_signal (ACE_SIGRTMIN, ACE_SIGRTMAX);
+
+ while (ACE_Proactor::event_loop_done () == 0)
+ ACE_Proactor::run_event_loop ();
+
+ delete_proactor ();
+
+ ACE_DEBUG ((LM_DEBUG, "(%t) MyTask finished\n"));
+ return 0;
+}
+
+class Receiver : public ACE_Service_Handler
+{
+public:
+
+ Receiver (void);
+ ~Receiver (void);
+
+ virtual void open (ACE_HANDLE handle,
+ ACE_Message_Block &message_block);
+ // This is called after the new connection has been accepted.
+
+ static long get_number_sessions (void) { return sessions_; }
+
+protected:
+ // These methods are called by the framework
+
+ virtual void handle_read_stream (const ACE_Asynch_Read_Stream::Result &result);
+ // This is called when asynchronous <read> operation from the socket
+ // complete.
+
+ virtual void handle_write_stream (const ACE_Asynch_Write_Stream::Result &result);
+ // This is called when an asynchronous <write> to the file
+ // completes.
+
+private:
+ int initiate_read_stream (void);
+ int initiate_write_stream (ACE_Message_Block & mb, int nBytes);
+ int check_destroy (void);
+
+ ACE_Asynch_Read_Stream rs_;
+ ACE_Asynch_Write_Stream ws_;
+ ACE_HANDLE handle_;
+ ACE_Recursive_Thread_Mutex mutex_;
+ long io_count_;
+ static long sessions_;
+};
+
+long Receiver::sessions_ = 0;
+
+Receiver::Receiver (void)
+ : handle_ (ACE_INVALID_HANDLE),
+ io_count_ (0)
+{
+ ACE_Guard<ACE_Recursive_Thread_Mutex> locker (mutex_);
+ sessions_++;
+ ACE_DEBUG ((LM_DEBUG, "Receiver Ctor sessions_=%d\n", sessions_));
+}
+
+Receiver::~Receiver (void)
+{
+ ACE_Guard<ACE_Recursive_Thread_Mutex> locker (mutex_);
+ sessions_--;
+ ACE_OS::closesocket (this->handle_);
+ ACE_DEBUG ((LM_DEBUG, "~Receiver Dtor sessions_=%d\n", sessions_));
+}
+
+// return true if we alive, false we commited suicide
+int
+Receiver::check_destroy (void)
+{
+ {
+ ACE_Guard<ACE_Recursive_Thread_Mutex> locker (mutex_);
+
+ if (io_count_ > 0)
+ return 1;
+ }
+
+ delete this;
+ return 0;
+}
+
+void
+Receiver::open (ACE_HANDLE handle,
+ ACE_Message_Block &)
+{
+ ACE_DEBUG ((LM_DEBUG,
+ "%N:%l:Receiver::open called\n"));
+
+ this->handle_ = handle;
+
+ if (this->ws_.open (*this, this->handle_) == -1)
+ ACE_ERROR ((LM_ERROR,
+ "%p\n",
+ "ACE_Asynch_Write_Stream::open"));
+ else if (this->rs_.open (*this, this->handle_) == -1)
+ ACE_ERROR ((LM_ERROR,
+ "%p\n",
+ "ACE_Asynch_Read_Stream::open"));
+ else
+ initiate_read_stream ();
+
+ check_destroy ();
+}
+
+int
+Receiver::initiate_read_stream (void)
+{
+ ACE_Guard<ACE_Recursive_Thread_Mutex> locker (mutex_);
+
+ ACE_Message_Block *mb = 0;
+ ACE_NEW_RETURN (mb,
+ ACE_Message_Block (BUFSIZ + 1),
+ -1);
+
+ // Inititiate read
+ if (this->rs_.read (*mb, mb->size ()- 1) == -1)
+ {
+ mb->release ();
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%p\n",
+ "ACE_Asynch_Read_Stream::read"),
+ -1);
+ }
+
+ io_count_++;
+ return 0;
+}
+
+int
+Receiver::initiate_write_stream (ACE_Message_Block &mb, int nbytes)
+{
+ ACE_Guard<ACE_Recursive_Thread_Mutex> locker (mutex_);
+ if (nbytes <= 0)
+ {
+ mb.release ();
+ ACE_ERROR_RETURN((LM_ERROR,
+ "ACE_Asynch_Write_Stream::write nbytes <0 "),
+ -1);
+ }
+
+ if (this->ws_.write (mb, nbytes) == -1)
+ {
+ mb.release ();
+ ACE_ERROR_RETURN((LM_ERROR,
+ "%p\n",
+ "ACE_Asynch_Write_Stream::write"),
+ -1);
+ }
+
+ io_count_++;
+ return 0;
+}
+
+void
+Receiver::handle_read_stream (const ACE_Asynch_Read_Stream::Result &result)
+{
+ // Reset pointers.
+ result.message_block ().rd_ptr ()[result.bytes_transferred ()] = '\0';
+
+ if (result.bytes_transferred () == 0 || result.error () != 0)
+ {
+ ACE_DEBUG ((LM_DEBUG, "handle_read_stream called\n"));
+ ACE_DEBUG ((LM_DEBUG, "********************\n"));
+ ACE_DEBUG ((LM_DEBUG, "%s = %d\n", "bytes_to_read", result.bytes_to_read ()));
+ ACE_DEBUG ((LM_DEBUG, "%s = %d\n", "handle", result.handle ()));
+ ACE_DEBUG ((LM_DEBUG, "%s = %d\n", "bytes_transfered", result.bytes_transferred ()));
+ ACE_DEBUG ((LM_DEBUG, "%s = %d\n", "act", (u_long) result.act ()));
+ ACE_DEBUG ((LM_DEBUG, "%s = %d\n", "success", result.success ()));
+ ACE_DEBUG ((LM_DEBUG, "%s = %d\n", "completion_key", (u_long) result.completion_key ()));
+ ACE_DEBUG ((LM_DEBUG, "%s = %d\n", "error", result.error ()));
+ ACE_DEBUG ((LM_DEBUG, "********************\n"));
+ ACE_DEBUG ((LM_DEBUG, "%s = %s\n", "message_block", result.message_block ().rd_ptr ()));
+ }
+
+ if (result.success () && result.bytes_transferred () != 0)
+ {
+ // Successful read: write the data to the file asynchronously.
+ // Note how we reuse the <ACE_Message_Block> for the writing.
+ // Therefore, we do not delete this buffer because it is handled
+ // in <handle_write_stream>.
+
+ if(this->initiate_write_stream (result.message_block (),
+ result.bytes_transferred ()) == 0)
+ {
+ if (duplex != 0)
+ {
+ // Initiate new read from the stream.
+ this->initiate_read_stream ();
+ }
+ }
+ }
+ else
+ {
+ result.message_block ().release ();
+ ACE_DEBUG ((LM_DEBUG, "Receiver completed\n"));
+ }
+
+ {
+ ACE_Guard<ACE_Recursive_Thread_Mutex> locker (mutex_);
+ io_count_--;
+ }
+ check_destroy ();
+}
+
+void
+Receiver::handle_write_stream (const ACE_Asynch_Write_Stream::Result &result)
+{
+ if (result.bytes_transferred () == 0 || result.error () != 0)
+ {
+ ACE_DEBUG ((LM_DEBUG, "handle_write_stream called\n"));
+
+ ACE_DEBUG ((LM_DEBUG, "********************\n"));
+ ACE_DEBUG ((LM_DEBUG, "%s = %d\n", "bytes_to_write", result.bytes_to_write ()));
+ ACE_DEBUG ((LM_DEBUG, "%s = %d\n", "handle", result.handle ()));
+ ACE_DEBUG ((LM_DEBUG, "%s = %d\n", "bytes_transfered", result.bytes_transferred ()));
+ ACE_DEBUG ((LM_DEBUG, "%s = %d\n", "act", (u_long) result.act ()));
+ ACE_DEBUG ((LM_DEBUG, "%s = %d\n", "success", result.success ()));
+ ACE_DEBUG ((LM_DEBUG, "%s = %d\n", "completion_key", (u_long) result.completion_key ()));
+ ACE_DEBUG ((LM_DEBUG, "%s = %d\n", "error", result.error ()));
+ ACE_DEBUG ((LM_DEBUG, "********************\n"));
+ }
+
+ result.message_block ().release ();
+
+ if (result.success () && result.bytes_transferred () != 0)
+ {
+ // This code is not robust enough to deal with short file writes
+ // (which hardly ever happen);-)
+ // ACE_ASSERT (result.bytes_to_write () == result.bytes_transferred ());
+
+ if (duplex == 0)
+ initiate_read_stream ();
+ }
+
+ {
+ ACE_Guard<ACE_Recursive_Thread_Mutex> locker (mutex_);
+ io_count_--;
+ }
+ check_destroy ();
+}
+
+class Sender : public ACE_Handler
+{
+ // = TITLE
+ // Sends welcome messages receives them back.
+public:
+ Sender (void);
+ ~Sender (void);
+ int open (const ACE_TCHAR *host, u_short port);
+ void close (void);
+ ACE_HANDLE handle (void) const;
+
+protected:
+ // These methods are called by the freamwork
+
+ virtual void handle_read_stream (const ACE_Asynch_Read_Stream::Result &result);
+ // This is called when asynchronous reads from the socket complete
+
+ virtual void handle_write_stream (const ACE_Asynch_Write_Stream::Result &result);
+ // This is called when asynchronous writes from the socket complete
+
+private:
+
+ int initiate_read_stream (void);
+ int initiate_write_stream (void);
+
+ ACE_SOCK_Stream stream_;
+ // Network I/O handle
+
+ ACE_Asynch_Write_Stream ws_;
+ // ws (write stream): for writing to the socket
+
+ ACE_Asynch_Read_Stream rs_;
+ // rs (read file): for reading from the socket
+
+ ACE_Message_Block welcome_message_;
+ // Welcome message
+
+ ACE_Recursive_Thread_Mutex mutex_;
+ long io_count_;
+};
+
+static char *data = "Welcome to Irfan World! Irfan RULES here !!\n";
+
+Sender::Sender (void)
+ : io_count_ (0)
+{
+ // Moment of inspiration... :-)
+ this->welcome_message_.init (data, ACE_OS::strlen (data));
+}
+
+Sender::~Sender (void)
+{
+ close ();
+}
+
+void Sender::close (void)
+{
+ this->stream_.close ();
+}
+
+ACE_HANDLE Sender::handle (void) const
+{
+ return this->stream_.get_handle ();
+}
+
+int Sender::open (const ACE_TCHAR *host, u_short port)
+{
+ // Initialize stuff
+ // Connect to remote host
+ ACE_INET_Addr address (port, host);
+ ACE_SOCK_Connector connector;
+
+ if (connector.connect (this->stream_,
+ address) == -1)
+ {
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%p\n",
+ "ACE_SOCK_Connector::connect"),
+ -1);
+ }
+
+ // Open ACE_Asynch_Write_Stream
+ if (this->ws_.open (*this) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%p\n",
+ "ACE_Asynch_Write_Stream::open"),
+ -1);
+
+ // Open ACE_Asynch_Read_Stream
+ if (this->rs_.open (*this) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%p\n",
+ "ACE_Asynch_Read_Stream::open"),
+ -1);
+
+ // Start an asynchronous transmit file
+ if (this->initiate_write_stream () == -1)
+ return -1;
+
+ if (duplex != 0)
+ // Start an asynchronous read file
+ if (this->initiate_read_stream () == -1)
+ return -1;
+
+ return 0;
+}
+
+int
+Sender::initiate_write_stream (void)
+{
+ ACE_Guard<ACE_Recursive_Thread_Mutex> locker (mutex_);
+
+ welcome_message_.rd_ptr(welcome_message_.base ());
+ welcome_message_.wr_ptr(welcome_message_.base ());
+ welcome_message_.wr_ptr (ACE_OS::strlen (data));
+
+ if (this->ws_.write (welcome_message_,
+ welcome_message_.length ()) == -1)
+ ACE_ERROR_RETURN((LM_ERROR,
+ "%p\n",
+ "ACE_Asynch_Write_Stream::write"),
+ -1);
+ io_count_++;
+ return 0;
+}
+
+int
+Sender::initiate_read_stream (void)
+{
+ ACE_Guard<ACE_Recursive_Thread_Mutex> locker (mutex_);
+
+ // Create a new <Message_Block>. Note that this message block will
+ // be used both to <read> data asynchronously from the socket and to
+ // <write> data asynchronously to the file.
+ ACE_DEBUG ((LM_DEBUG,
+ "initiate_read_stream called\n"));
+
+ ACE_Message_Block *mb = 0;
+ ACE_NEW_RETURN (mb,
+ ACE_Message_Block (BUFSIZ + 1),
+ -1);
+
+ // Inititiate read
+ if (this->rs_.read (*mb, mb->size ()- 1) == -1)
+ {
+ mb->release ();
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%p\n",
+ "ACE_Asynch_Read_Stream::read"),
+ -1);
+ }
+
+ io_count_++;
+ return 0;
+}
+
+void
+Sender::handle_write_stream (const ACE_Asynch_Write_Stream::Result &result)
+{
+ if (result.bytes_transferred () == 0 || result.error () != 0)
+ {
+ ACE_DEBUG ((LM_DEBUG, "handle_write_stream called\n"));
+
+ // Reset pointers.
+ result.message_block ().rd_ptr (result.message_block ().rd_ptr () - result.bytes_transferred ());
+
+ ACE_DEBUG ((LM_DEBUG, "********************\n"));
+ ACE_DEBUG ((LM_DEBUG, "%s = %d\n", "bytes_to_write", result.bytes_to_write ()));
+ ACE_DEBUG ((LM_DEBUG, "%s = %d\n", "handle", result.handle ()));
+ ACE_DEBUG ((LM_DEBUG, "%s = %d\n", "bytes_transfered", result.bytes_transferred ()));
+ ACE_DEBUG ((LM_DEBUG, "%s = %d\n", "act", (u_long) result.act ()));
+ ACE_DEBUG ((LM_DEBUG, "%s = %d\n", "success", result.success ()));
+ ACE_DEBUG ((LM_DEBUG, "%s = %d\n", "completion_key", (u_long) result.completion_key ()));
+ ACE_DEBUG ((LM_DEBUG, "%s = %d\n", "error", result.error ()));
+ ACE_DEBUG ((LM_DEBUG, "********************\n"));
+ ACE_DEBUG ((LM_DEBUG, "%s = %s\n", "message_block", result.message_block ().rd_ptr ()));
+ }
+
+ // Simplify just for Test
+ if (result.success () && result.bytes_transferred () != 0)
+ {
+ if (duplex != 0) // full duplex, continue write
+ initiate_write_stream ();
+ else // half-duplex read reply, after read we will start write
+ initiate_read_stream ();
+ }
+
+ {
+ ACE_Guard<ACE_Recursive_Thread_Mutex> locker (mutex_);
+ io_count_--;
+ }
+}
+
+void
+Sender::handle_read_stream (const ACE_Asynch_Read_Stream::Result &result)
+{
+ if (result.bytes_transferred () == 0 || result.error () != 0)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ "handle_read_stream called\n"));
+
+ // Reset pointers.
+ result.message_block ().rd_ptr ()[result.bytes_transferred ()] = '\0';
+
+ ACE_DEBUG ((LM_DEBUG, "********************\n"));
+ ACE_DEBUG ((LM_DEBUG, "%s = %d\n", "bytes_to_read", result.bytes_to_read ()));
+ ACE_DEBUG ((LM_DEBUG, "%s = %d\n", "handle", result.handle ()));
+ ACE_DEBUG ((LM_DEBUG, "%s = %d\n", "bytes_transfered", result.bytes_transferred ()));
+ ACE_DEBUG ((LM_DEBUG, "%s = %d\n", "act", (u_long) result.act ()));
+ ACE_DEBUG ((LM_DEBUG, "%s = %d\n", "success", result.success ()));
+ ACE_DEBUG ((LM_DEBUG, "%s = %d\n", "completion_key", (u_long) result.completion_key ()));
+ ACE_DEBUG ((LM_DEBUG, "%s = %d\n", "error", result.error ()));
+ ACE_DEBUG ((LM_DEBUG, "********************\n"));
+ ACE_DEBUG ((LM_DEBUG, "%s = %s\n", "message_block", result.message_block ().rd_ptr ()));
+ }
+
+ result.message_block().release ();
+
+ if (result.success () && result.bytes_transferred () != 0)
+ {
+ // Successful read: write the data to the file asynchronously.
+ // Note how we reuse the <ACE_Message_Block> for the writing.
+ // Therefore, we do not delete this buffer because it is handled
+ // in <handle_write_stream>.
+
+ if (duplex != 0) // full duplex, continue read
+ initiate_read_stream ();
+ else // half-duplex writey, after write we will start read
+ initiate_write_stream ();
+ }
+
+ {
+ ACE_Guard<ACE_Recursive_Thread_Mutex> locker (mutex_);
+ io_count_--;
+ }
+}
+
+static int
+set_proactor_type (const char *ptype)
+{
+ if (!ptype)
+ return false;
+
+ switch (toupper (*ptype))
+ {
+ case 'D' : proactor_type = 0; return true;
+ case 'A' : proactor_type = 1; return true;
+ case 'I' : proactor_type = 2; return true;
+#if defined (sun)
+ case 'S' : proactor_type = 3; return true;
+#endif /* sun */
+ }
+ return false;
+}
+
+static int
+parse_args (int argc, ACE_TCHAR *argv[])
+{
+ ACE_Get_Opt get_opt (argc, argv, ACE_TEXT("t:o:n:p:d:h:s:u"));
+ int c;
+
+ while ((c = get_opt ()) != EOF)
+ switch (c)
+ {
+ case 'd': // duplex
+ duplex = ACE_OS::atoi (get_opt.opt_arg ());
+ break;
+ case 'h': // host for sender
+ host = get_opt.opt_arg ();
+ break;
+ case 'p': // port number
+ port = ACE_OS::atoi (get_opt.opt_arg ());
+ break;
+ case 'n': // thread pool size
+ threads = ACE_OS::atoi (get_opt.opt_arg ());
+ break;
+ case 's': // number of senders
+ senders = ACE_OS::atoi (get_opt.opt_arg ());
+ if (senders > MaxSenders)
+ senders = MaxSenders;
+ break;
+ case 'o': // max number of aio for proactor
+ max_aio_operations = ACE_OS::atoi (get_opt.opt_arg ());
+ break;
+ case 't': // Proactor Type
+ if (set_proactor_type (get_opt.opt_arg ()))
+ break;
+ case 'u':
+ default:
+ ACE_ERROR ((LM_ERROR, "%p.",
+ "\nusage:"
+ "\n-o <max number of started aio operations for Proactor>"
+ "\n-t <Proactor type> UNIX-only, Win32-default always:"
+ "\n a AIOCB"
+ "\n i SIG"
+ "\n s SUN"
+ "\n d default"
+ "\n-d <duplex mode 1-on/0-off>"
+ "\n-h <host> for Sender mode"
+ "\n-n <number threads for Proactor pool>"
+ "\n-p <port to listen/connect>"
+ "\n-s <number of sender's instances>"
+ "\n-u show this message"
+ "\n"));
+
+ return -1;
+ }
+
+ return 0;
+}
+
+int
+ACE_TMAIN (int argc, ACE_TCHAR *argv[])
+{
+#if defined (sun)
+ ACE_DEBUG ((LM_DEBUG, "\nSUN defined!\n"));
+#endif
+ if (parse_args (argc, argv) == -1)
+ return -1;
+
+ disable_signal (ACE_SIGRTMIN, ACE_SIGRTMAX);
+
+ MyTask task1;
+
+ if (task1.activate (THR_NEW_LWP, threads) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%p.\n",
+ "main"),
+ -1);
+
+ // wait for creation of Proactor
+ task1.waitready ();
+
+ Sender * send_list[MaxSenders];
+
+ ACE_Asynch_Acceptor<Receiver> acceptor;
+
+ int rc = -1;
+ int i;
+ char c;
+
+ if (host == 0) // Acceptor
+ {
+ // Simplify, initial read with zero size
+ if (acceptor.open (ACE_INET_Addr (port),0,1) == 0)
+ rc = 1;
+ }
+ else
+ {
+ for (i = 0; i < senders; ++i)
+ send_list[i] = new Sender;
+
+ for (i = 0; i < senders; ++i)
+ if (send_list[i]->open (host, port) == 0)
+ rc++;
+ }
+
+ if (rc > 0)
+ {
+ cout << "Press any key to stop=>" << flush;
+ cin.clear ();
+ cin >> c;
+ }
+
+ ACE_Proactor::end_event_loop ();
+
+ if (host != 0) // we are sender
+ {
+ for (i = 0; i < senders; ++i)
+ send_list[i]->close ();
+ }
+
+
+ ACE_Thread_Manager *tm =
+ ACE_Thread_Manager::instance();
+
+ tm->wait_task (&task1);
+
+ cout << "\nNumber of Receivers objects="
+ << Receiver::get_number_sessions ()
+ << flush;
+
+ for (i = 0; i < senders; ++i)
+ {
+ delete (send_list[i]);
+ send_list[i] = 0;
+ }
+
+ return 0;
+}
+
+static int
+disable_signal (int sigmin, int sigmax)
+{
+#ifndef ACE_WIN32
+
+ sigset_t signal_set;
+ if (sigemptyset (&signal_set) == - 1)
+ ACE_ERROR ((LM_ERROR,
+ "Error:(%P | %t):%p\n",
+ "sigemptyset failed"));
+
+ for (int i = sigmin; i <= sigmax; i++)
+ sigaddset (&signal_set, i);
+
+ // Put the <signal_set>.
+ if (ACE_OS::pthread_sigmask (SIG_BLOCK, &signal_set, 0) != 0)
+ ACE_ERROR ((LM_ERROR,
+ "Error:(%P | %t):%p\n",
+ "pthread_sigmask failed"));
+#endif /* ACE_WIN32 */
+
+ return 1;
+}
+
+// Get the <signal_set> back from the OS.
+
+#if 0
+static int
+print_sigmask (void)
+{
+#ifndef ACE_WIN32
+ sigset_t mask;
+ int member = 0;
+
+ COUT ("\n=============Signal Mask==========")
+
+ if (ACE_OS::pthread_sigmask (SIG_SETMASK, 0, & mask) != 0)
+ ACE_ERROR ((LM_ERROR,
+ "Error:(%P | %t):%p\n",
+ "ACE_OS::pthread_sigmask failed"));
+ else
+ for (int i = 1; i < 1000; i++)
+ {
+ member = sigismember (&mask,i);
+
+ COUT ("\nSig ")
+ COUT (i)
+ COUT (" is ")
+ COUT (member)
+
+ if (member == -1)
+ break;
+ }
+
+#endif /* ACE_WIN32 */
+ return 0;
+}
+#endif /* 0 */
+
+#endif /* ACE_WIN32 && !ACE_HAS_WINCE || ACE_HAS_AIO_CALLS*/
diff --git a/ACE/examples/Reactor/Proactor/test_timeout.cpp b/ACE/examples/Reactor/Proactor/test_timeout.cpp
new file mode 100644
index 00000000000..39351717db9
--- /dev/null
+++ b/ACE/examples/Reactor/Proactor/test_timeout.cpp
@@ -0,0 +1,130 @@
+// $Id: test_timeout.cpp
+
+// ============================================================================
+//
+// = LIBRARY
+// examples
+//
+// = FILENAME
+// test_timeout.cpp
+//
+// = DESCRIPTION
+//
+// This example application shows how to write event loops that
+// handle events for some fixed amount of time. Note that any
+// thread in the Proactor thread pool can call back the handler. On
+// POSIX4 systems, this test works only with POSIX_SIG_Proactor,
+// which can work with multiple threads.
+//
+// = AUTHOR
+// Irfan Pyarali and Alexander Babu Arulanthu
+//
+// ============================================================================
+
+#include "ace/Proactor.h"
+#include "ace/Task.h"
+#include "ace/Atomic_Op.h"
+#include "ace/OS_NS_sys_time.h"
+#include "ace/OS_NS_unistd.h"
+#include "ace/OS_main.h"
+
+ACE_RCSID(Proactor, test_timeout, "$Id$")
+
+#if ((defined (ACE_WIN32) && !defined (ACE_HAS_WINCE)) || \
+ (defined (ACE_HAS_AIO_CALLS)) && !defined (ACE_POSIX_AIOCB_PROACTOR))
+ // This only works on Win32 platforms and on Unix platforms supporting
+ // POSIX aio calls.
+
+class Timeout_Handler : public ACE_Handler
+{
+ // = TITLE
+ // Generic timeout handler.
+public:
+ Timeout_Handler (void)
+ : start_time_ (ACE_OS::gettimeofday ())
+ {
+ }
+
+ virtual void handle_time_out (const ACE_Time_Value &tv,
+ const void *arg)
+ {
+ // Print out when timeouts occur.
+ ACE_DEBUG ((LM_DEBUG, "(%t) %d timeout occurred for %s @ %d.\n",
+ ++count_,
+ (char *) arg,
+ (tv - this->start_time_).sec ()));
+
+ // Sleep for a while
+ ACE_OS::sleep (4);
+ }
+
+private:
+ ACE_Atomic_Op <ACE_SYNCH_MUTEX, int> count_;
+ // Number of the timer event.
+
+ ACE_Time_Value start_time_;
+ // Starting time of the test.
+};
+
+class Worker : public ACE_Task <ACE_NULL_SYNCH>
+{
+public:
+ int svc (void)
+ {
+ // Handle events for 13 seconds.
+ ACE_Time_Value run_time (13);
+
+ ACE_DEBUG ((LM_DEBUG, "(%t):Starting svc routine\n"));
+
+ if (ACE_Proactor::run_event_loop(run_time) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, "(%t):%p.\n", "Worker::svc"), -1);
+
+ ACE_DEBUG ((LM_DEBUG, "(%t) work complete\n"));
+
+ return 0;
+ }
+};
+
+int
+ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ Timeout_Handler handler;
+
+ // Register a 2 second timer.
+ ACE_Time_Value foo_tv (2);
+ if (ACE_Proactor::instance ()->schedule_timer (handler,
+ (void *) "Foo",
+ ACE_Time_Value::zero,
+ foo_tv) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "schedule_timer"), -1);
+
+ // Register a 3 second timer.
+ ACE_Time_Value bar_tv (3);
+ if (ACE_Proactor::instance ()->schedule_timer (handler,
+ (void *) "Bar",
+ ACE_Time_Value::zero,
+ bar_tv) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "schedule_timer"), -1);
+
+ Worker worker;
+
+ if (worker.activate (THR_NEW_LWP, 10) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, "%p.\n", "main"), -1);
+
+ ACE_Thread_Manager::instance ()->wait ();
+
+ return 0;
+}
+
+#else /* ACE_WIN32 && !ACE_HAS_WINCE || ACE_HAS_AIO_CALLS && !ACE_POSIX_AIOCB_PROACTOR*/
+
+int
+main (int, char *[])
+{
+ ACE_DEBUG ((LM_DEBUG,
+ "This example is multithreaded version of test_timeout_st.cpp\n"
+ "This doesnt work on this platform !!!\n"));
+ return 1;
+}
+
+#endif /* ACE_WIN32 && !ACE_HAS_WINCE || ACE_HAS_AIO_CALLS && !ACE_POSIX_AIOCB_PROACTOR*/
diff --git a/ACE/examples/Reactor/Proactor/test_timeout_st.cpp b/ACE/examples/Reactor/Proactor/test_timeout_st.cpp
new file mode 100644
index 00000000000..ae44c2ba1f4
--- /dev/null
+++ b/ACE/examples/Reactor/Proactor/test_timeout_st.cpp
@@ -0,0 +1,99 @@
+// $Id$
+
+// ============================================================================
+//
+// = LIBRARY
+// examples
+//
+// = FILENAME
+// test_timeout_st.cpp
+//
+// = DESCRIPTION
+//
+// This example application shows how to write event loops that
+// handle events for some fixed amount of time. This is the single
+// threaded version of the test_timeout.cpp application.
+//
+// = AUTHOR
+// Irfan Pyarali and Alexander Babu Arulanthu
+//
+// ============================================================================
+
+#include "ace/Proactor.h"
+#include "ace/OS_main.h"
+
+ACE_RCSID(Proactor, test_timeout, "$Id$")
+
+#if ((defined (ACE_WIN32) && !defined (ACE_HAS_WINCE)) || (defined (ACE_HAS_AIO_CALLS)))
+// This only works on Win32 platforms and on Unix platforms supporting
+// POSIX aio calls.
+
+class Timeout_Handler : public ACE_Handler
+{
+ // = TITLE
+ // Generic timeout handler.
+
+public:
+ Timeout_Handler (void)
+ : count_ (0),
+ start_time_ (ACE_OS::gettimeofday ())
+ {
+ }
+
+ virtual void handle_time_out (const ACE_Time_Value &tv,
+ const void *arg)
+ {
+ // Print out when timeouts occur.
+ ACE_DEBUG ((LM_DEBUG, "(%t) %d timeout occurred for %s @ %d.\n",
+ ++count_,
+ (char *) arg,
+ (tv - this->start_time_).sec ()));
+ }
+
+private:
+ int count_;
+ // Sequence number for the timeouts.
+
+ ACE_Time_Value start_time_;
+ // Starting time of the test.
+};
+
+
+int
+ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ Timeout_Handler handler;
+
+ // Register a 2 second timer.
+ ACE_Time_Value foo_tv (2);
+ if (ACE_Proactor::instance ()->schedule_timer (handler,
+ (void *) "Foo",
+ ACE_Time_Value::zero,
+ foo_tv) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "schedule_timer"), -1);
+
+ // Register a 3 second timer.
+ ACE_Time_Value bar_tv (3);
+ if (ACE_Proactor::instance ()->schedule_timer (handler,
+ (void *) "Bar",
+ ACE_Time_Value::zero,
+ bar_tv) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "schedule_timer"), -1);
+
+ // Handle events for 13 seconds.
+ ACE_Time_Value run_time (13);
+
+ ACE_DEBUG ((LM_DEBUG, "Starting event loop\n"));
+
+ // Run the event loop.
+ if (ACE_Proactor::run_event_loop(run_time) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "(%t):%p.\n", "Worker::svc"),
+ 1);
+
+ ACE_DEBUG ((LM_DEBUG, "Ending event loop\n"));
+
+ return 0;
+}
+
+#endif /* ACE_WIN32 && !ACE_HAS_WINCE || ACE_HAS_AIO_CALLS*/
diff --git a/ACE/examples/Reactor/Proactor/test_udp_proactor.cpp b/ACE/examples/Reactor/Proactor/test_udp_proactor.cpp
new file mode 100644
index 00000000000..49d834a2884
--- /dev/null
+++ b/ACE/examples/Reactor/Proactor/test_udp_proactor.cpp
@@ -0,0 +1,432 @@
+// $Id$
+
+// ============================================================================
+//
+// = LIBRARY
+// examples
+//
+// = FILENAME
+// test_udp_proactor.cpp
+//
+// = DESCRIPTION
+// This program illustrates how the <ACE_Proactor> can be used to
+// implement an application that does asynchronous operations using
+// datagrams.
+//
+// = AUTHOR
+// Irfan Pyarali <irfan@cs.wustl.edu> and
+// Roger Tragin <r.tragin@computer.org>
+//
+// ============================================================================
+
+#include "ace/OS_NS_string.h"
+#include "ace/OS_main.h"
+#include "ace/Proactor.h"
+#include "ace/Asynch_IO.h"
+#include "ace/INET_Addr.h"
+#include "ace/SOCK_Dgram.h"
+#include "ace/Message_Block.h"
+#include "ace/Get_Opt.h"
+#include "ace/Log_Msg.h"
+
+ACE_RCSID(Proactor, test_udp_proactor, "test_proactor.cpp,v 1.29 2001/02/02 23:41:16 shuston Exp")
+
+#if defined (ACE_WIN32) && !defined (ACE_HAS_WINCE) || defined (ACE_HAS_AIO_CALLS)
+ // This only works on Win32 platforms.
+
+// Host that we're connecting to.
+static ACE_TCHAR *host = 0;
+
+// Port that we're receiving connections on.
+static u_short port = ACE_DEFAULT_SERVER_PORT;
+
+// Keep track of when we're done.
+static int done = 0;
+
+class Receiver : public ACE_Service_Handler
+{
+ // = TITLE
+ // This class will receive data from
+ // the network connection and dump it to a file.
+public:
+ // = Initialization and termination.
+ Receiver (void);
+ ~Receiver (void);
+
+ int open_addr (const ACE_INET_Addr &localAddr);
+
+protected:
+ // These methods are called by the framework
+
+ /// This method will be called when an asynchronous read completes on
+ /// a UDP socket.
+ virtual void handle_read_dgram (const ACE_Asynch_Read_Dgram::Result &result);
+
+private:
+ ACE_SOCK_Dgram sock_dgram_;
+
+ ACE_Asynch_Read_Dgram rd_;
+ // rd (read dgram): for reading from a UDP socket.
+ const char* completion_key_;
+ const char* act_;
+};
+
+Receiver::Receiver (void)
+ : completion_key_ ("Receiver Completion Key"),
+ act_ ("Receiver ACT")
+{
+}
+
+Receiver::~Receiver (void)
+{
+ sock_dgram_.close ();
+}
+
+int
+Receiver::open_addr (const ACE_INET_Addr &localAddr)
+{
+ ACE_DEBUG ((LM_DEBUG,
+ "%N:%l:Receiver::open_addr called\n"));
+
+ // Create a local UDP socket to receive datagrams.
+ if (this->sock_dgram_.open (localAddr) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%p\n",
+ "ACE_SOCK_Dgram::open"), -1);
+
+ // Initialize the asynchronous read.
+ if (this->rd_.open (*this,
+ this->sock_dgram_.get_handle (),
+ this->completion_key_,
+ ACE_Proactor::instance ()) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%p\n",
+ "ACE_Asynch_Read_Dgram::open"), -1);
+
+ // Create a buffer to read into. We are using scatter/gather to
+ // read the message header and message body into 2 buffers
+
+ // create a message block to read the message header
+ ACE_Message_Block* msg = 0;
+ ACE_NEW_RETURN (msg, ACE_Message_Block (1024), -1);
+
+ // the next line sets the size of the header, even though we
+ // allocated a the message block of 1k, by setting the size to 20
+ // bytes then the first 20 bytes of the reveived datagram will be
+ // put into this message block.
+ msg->size (20); // size of header to read is 20 bytes
+
+ // create a message block to read the message body
+ ACE_Message_Block* body = 0;
+ ACE_NEW_RETURN (body, ACE_Message_Block (1024), -1);
+ // The message body will not exceed 1024 bytes, at least not in this test.
+
+ // set body as the cont of msg. This associates the 2 message
+ // blocks so that a read will fill the first block (which is the
+ // header) up to size (), and use the cont () block for the rest of
+ // the data. You can chain up to IOV_MAX message block using this
+ // method.
+ msg->cont (body);
+
+ // ok lets do the asynch read
+ size_t number_of_bytes_recvd = 0;
+
+ int res = rd_.recv (msg,
+ number_of_bytes_recvd,
+ 0,
+ PF_INET,
+ this->act_);
+ switch (res)
+ {
+ case 0:
+ // this is a good error. The proactor will call our handler when the
+ // read has completed.
+ break;
+ case 1:
+ // actually read something, we will handle it in the handler callback
+ ACE_DEBUG ((LM_DEBUG, "********************\n"));
+ ACE_DEBUG ((LM_DEBUG,
+ "%s = %d\n",
+ "bytes recieved immediately",
+ number_of_bytes_recvd));
+ ACE_DEBUG ((LM_DEBUG, "********************\n"));
+ res = 0;
+ break;
+ case -1:
+ // Something else went wrong.
+ ACE_ERROR ((LM_ERROR,
+ "%p\n",
+ "ACE_Asynch_Read_Dgram::recv"));
+ // the handler will not get called in this case so lets clean up our msg
+ msg->release ();
+ break;
+ default:
+ // Something undocumented really went wrong.
+ ACE_ERROR ((LM_ERROR,
+ "%p\n",
+ "ACE_Asynch_Read_Dgram::recv"));
+ msg->release ();
+ break;
+ }
+
+ return res;
+}
+
+void
+Receiver::handle_read_dgram (const ACE_Asynch_Read_Dgram::Result &result)
+{
+ ACE_DEBUG ((LM_DEBUG,
+ "handle_read_dgram called\n"));
+
+ ACE_DEBUG ((LM_DEBUG, "********************\n"));
+ ACE_DEBUG ((LM_DEBUG, "%s = %d\n", "bytes_to_read", result.bytes_to_read ()));
+ ACE_DEBUG ((LM_DEBUG, "%s = %d\n", "handle", result.handle ()));
+ ACE_DEBUG ((LM_DEBUG, "%s = %d\n", "bytes_transfered", result.bytes_transferred ()));
+ ACE_INET_Addr peerAddr;
+ result.remote_address (peerAddr);
+ ACE_DEBUG ((LM_DEBUG, "%s = %s:%d\n", "peer_address", peerAddr.get_host_addr (), peerAddr.get_port_number ()));
+ ACE_DEBUG ((LM_DEBUG, "%s = %d\n", "flags", result.flags ()));
+ ACE_DEBUG ((LM_DEBUG, "%s = %s\n", "act", result.act ()));
+ ACE_DEBUG ((LM_DEBUG, "%s = %d\n", "success", result.success ()));
+ ACE_DEBUG ((LM_DEBUG, "%s = %s\n", "completion_key", result.completion_key ()));
+ ACE_DEBUG ((LM_DEBUG, "%s = %d\n", "error", result.error ()));
+ ACE_DEBUG ((LM_DEBUG, "********************\n"));
+
+ if (result.success () && result.bytes_transferred () != 0)
+ {
+ // loop through our message block and print out the contents
+ for (const ACE_Message_Block* msg = result.message_block (); msg != 0; msg = msg->cont ())
+ { // use msg->length () to get the number of bytes written to the message
+ // block.
+ ACE_DEBUG ((LM_DEBUG, "Buf=[size=<%d>", msg->length ()));
+ for (u_long i = 0; i < msg->length (); ++i)
+ ACE_DEBUG ((LM_DEBUG,
+ "%c", (msg->rd_ptr ())[i]));
+ ACE_DEBUG ((LM_DEBUG, "]\n"));
+ }
+ }
+
+ ACE_DEBUG ((LM_DEBUG,
+ "Receiver completed\n"));
+
+ // No need for this message block anymore.
+ result.message_block ()->release ();
+
+ // Note that we are done with the test.
+ done++;
+}
+
+class Sender : public ACE_Handler
+{
+ // = TITLE
+ // The class will be created by <main>.
+public:
+ Sender (void);
+ ~Sender (void);
+ int open (const ACE_TCHAR *host, u_short port);
+
+protected:
+ // These methods are called by the freamwork
+
+ virtual void handle_write_dgram (const ACE_Asynch_Write_Dgram::Result &result);
+ // This is called when asynchronous writes from the dgram socket
+ // complete
+
+private:
+
+ ACE_SOCK_Dgram sock_dgram_;
+ // Network I/O handle
+
+ ACE_Asynch_Write_Dgram wd_;
+ // wd (write dgram): for writing to the socket
+
+ const char* completion_key_;
+ const char* act_;
+};
+
+Sender::Sender (void)
+ : completion_key_ ("Sender completion key"),
+ act_ ("Sender ACT")
+{
+}
+
+Sender::~Sender (void)
+{
+ this->sock_dgram_.close ();
+}
+
+int
+Sender::open (const ACE_TCHAR *host,
+ u_short port)
+{
+ // Initialize stuff
+
+ if (this->sock_dgram_.open (ACE_INET_Addr::sap_any) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%p\n",
+ "ACE_SOCK_Dgram::open"), -1);
+
+ // Initialize the asynchronous read.
+ if (this->wd_.open (*this,
+ this->sock_dgram_.get_handle (),
+ this->completion_key_,
+ ACE_Proactor::instance ()) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%p\n",
+ "ACE_Asynch_Write_Dgram::open"), -1);
+
+ // We are using scatter/gather to send the message header and
+ // message body using 2 buffers
+
+ // create a message block for the message header
+ ACE_Message_Block* msg = 0;
+ ACE_NEW_RETURN (msg, ACE_Message_Block (100), -1);
+ const char raw_msg [] = "To be or not to be.";
+ // Copy buf into the Message_Block and update the wr_ptr ().
+ msg->copy (raw_msg, ACE_OS::strlen (raw_msg) + 1);
+
+ // create a message block for the message body
+ ACE_Message_Block* body = 0;
+ ACE_NEW_RETURN (body, ACE_Message_Block (100), -1);
+ ACE_OS::memset (body->wr_ptr (), 'X', 100);
+ body->wr_ptr (100); // always remember to update the wr_ptr ()
+
+ // set body as the cont of msg. This associates the 2 message blocks so
+ // that a send will send the first block (which is the header) up to
+ // length (), and use the cont () to get the next block to send. You can
+ // chain up to IOV_MAX message block using this method.
+ msg->cont (body);
+
+ // do the asynch send
+ size_t number_of_bytes_sent = 0;
+ ACE_INET_Addr serverAddr (port, host);
+ int res = this->wd_.send (msg, number_of_bytes_sent, 0, serverAddr, this->act_);
+
+ switch (res)
+ {
+ case 0:
+ // this is a good error. The proactor will call our handler when the
+ // send has completed.
+ break;
+ case 1:
+ // actually sent something, we will handle it in the handler callback
+ ACE_DEBUG ((LM_DEBUG, "********************\n"));
+ ACE_DEBUG ((LM_DEBUG,
+ "%s = %d\n",
+ "bytes sent immediately",
+ number_of_bytes_sent));
+ ACE_DEBUG ((LM_DEBUG, "********************\n"));
+ res = 0;
+ break;
+ case -1:
+ // Something else went wrong.
+ ACE_ERROR ((LM_ERROR,
+ "%p\n",
+ "ACE_Asynch_Write_Dgram::recv"));
+ // the handler will not get called in this case so lets clean up our msg
+ msg->release ();
+ break;
+ default:
+ // Something undocumented really went wrong.
+ ACE_ERROR ((LM_ERROR,
+ "%p\n",
+ "ACE_Asynch_Write_Dgram::recv"));
+ msg->release ();
+ break;
+ }
+ return res;
+}
+
+void
+Sender::handle_write_dgram (const ACE_Asynch_Write_Dgram::Result &result)
+{
+ ACE_DEBUG ((LM_DEBUG,
+ "handle_write_dgram called\n"));
+
+ ACE_DEBUG ((LM_DEBUG, "********************\n"));
+ ACE_DEBUG ((LM_DEBUG, "%s = %d\n", "bytes_to_write", result.bytes_to_write ()));
+ ACE_DEBUG ((LM_DEBUG, "%s = %d\n", "handle", result.handle ()));
+ ACE_DEBUG ((LM_DEBUG, "%s = %d\n", "bytes_transfered", result.bytes_transferred ()));
+ ACE_DEBUG ((LM_DEBUG, "%s = %d\n", "flags", result.flags ()));
+ ACE_DEBUG ((LM_DEBUG, "%s = %s\n", "act", result.act ()));
+ ACE_DEBUG ((LM_DEBUG, "%s = %d\n", "success", result.success ()));
+ ACE_DEBUG ((LM_DEBUG, "%s = %s\n", "completion_key", result.completion_key ()));
+ ACE_DEBUG ((LM_DEBUG, "%s = %d\n", "error", result.error ()));
+ ACE_DEBUG ((LM_DEBUG, "********************\n"));
+
+
+ ACE_DEBUG ((LM_DEBUG,
+ "Sender completed\n"));
+
+ // No need for this message block anymore.
+ result.message_block ()->release ();
+
+ // Note that we are done with the test.
+ done++;
+}
+
+static int
+parse_args (int argc, ACE_TCHAR *argv[])
+{
+ ACE_Get_Opt get_opt (argc, argv, ACE_TEXT ("h:p:"));
+ int c;
+
+ while ((c = get_opt ()) != EOF)
+ switch (c)
+ {
+ case 'h':
+ host = get_opt.opt_arg ();
+ break;
+ case 'p':
+ port = ACE_OS::atoi (get_opt.opt_arg ());
+ break;
+ default:
+ ACE_ERROR_RETURN ((LM_ERROR, "%p.\n",
+ "usage :\n"
+ "-h <host>\n"), -1);
+ }
+
+ return 0;
+}
+
+int
+ACE_TMAIN (int argc, ACE_TCHAR *argv[])
+{
+ if (parse_args (argc, argv) == -1)
+ return -1;
+
+ Sender sender;
+
+ Receiver receiver;
+
+ // If passive side
+ if (host == 0)
+ {
+ if (receiver.open_addr (ACE_INET_Addr (port)) == -1)
+ return -1;
+ }
+ // If active side
+ else if (sender.open (host, port) == -1)
+ return -1;
+
+ for (int success = 1;
+ success > 0 && !done;
+ )
+ // Dispatch events via Proactor singleton.
+ success = ACE_Proactor::instance ()->handle_events ();
+
+ return 0;
+}
+
+#else /* ACE_WIN32 && !ACE_HAS_WINCE || ACE_HAS_AIO_CALLS*/
+
+int
+ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ ACE_DEBUG ((LM_DEBUG,
+ "This example does not work on this platform.\n"));
+ return 1;
+}
+
+#endif /* ACE_WIN32 && !ACE_HAS_WINCE || ACE_HAS_AIO_CALLS*/
+
diff --git a/ACE/examples/Reactor/README b/ACE/examples/Reactor/README
new file mode 100644
index 00000000000..fefaeeaf317
--- /dev/null
+++ b/ACE/examples/Reactor/README
@@ -0,0 +1,20 @@
+This directory contains subdirectories that test the ACE Reactor and Proactor
+
+ . Dgram
+ Tests the CODgram and Dgram classes with the Reactor.
+
+ . Misc
+ Various miscellaneous tests of Reactor functionality
+ (e.g., signals, timers, notification, etc.).
+
+ . Multicast
+ Tests out the ACE multicast capabilities in conjunction
+ with the Reactor.
+
+ . Ntalker
+ A program that implements a multicast "chat" program.
+
+
+ . Proactor
+ A program that illustrates the "Proactive" version of
+ the Reactor
diff --git a/ACE/examples/Reactor/TP_Reactor/AcceptHandler.cpp b/ACE/examples/Reactor/TP_Reactor/AcceptHandler.cpp
new file mode 100644
index 00000000000..7ae34d2b2b4
--- /dev/null
+++ b/ACE/examples/Reactor/TP_Reactor/AcceptHandler.cpp
@@ -0,0 +1,106 @@
+/*
+ * $Id$
+ *
+ * ACE reactor demonstration
+ *
+ * Date: 26-Jan-2006
+ */
+
+#include <ace/Auto_Ptr.h>
+#include <ace/INET_Addr.h>
+
+#include "common.h"
+#include "AcceptHandler.h"
+#include "ReadHandler.h"
+
+AcceptHandler:: AcceptHandler(ACE_Reactor *reactor) :
+ ACE_Event_Handler(),
+ mReactor(reactor == 0 ? ACE_Reactor::instance() : reactor),
+ mAcceptor() {
+ ACE_TRACE("AcceptHandler:: AcceptHandler(ACE_Reactor *)");
+}
+
+AcceptHandler::~AcceptHandler() {
+ ACE_TRACE("AcceptHandler::~AcceptHandler()");
+}
+
+int AcceptHandler::open(void) {
+ ACE_TRACE("AcceptHandler::open(void)");
+
+ // create the local address used for the service (PORT is from common.h)
+ ACE_INET_Addr addr(PORT);
+
+ // open a port using the acceptor; reuse the address later
+ if (mAcceptor.open(addr, 1) == -1)
+ ACE_ERROR_RETURN((LM_ERROR, ACE_TEXT("%N:%l: Failed to open ")
+ ACE_TEXT ("listening socket. (errno = %i: %m)\n"), errno), -1);
+
+ // register the handler with the reactor
+ if (mReactor->register_handler(this,
+ ACE_Event_Handler::ACCEPT_MASK) == -1) {
+ ACE_ERROR((LM_ERROR, ACE_TEXT("%N:%l: Failed to register accept ")
+ ACE_TEXT ("handler. (errno = %i: %m)\n"), errno));
+
+ // don't leave the acceptor open
+ if (mAcceptor.close() == -1)
+ ACE_ERROR((LM_ERROR, ACE_TEXT("%N:%l: Failed to close the socket ")
+ ACE_TEXT ("after previous error. (errno = %i: %m)\n"),
+ errno));
+ return -1;
+ }
+
+ return 0;
+}
+
+ACE_HANDLE AcceptHandler::get_handle(void) const {
+ ACE_TRACE("AcceptHandler::get_handle(void)");
+ return mAcceptor.get_handle();
+}
+
+int AcceptHandler::handle_input(ACE_HANDLE) {
+ ACE_TRACE("AcceptHandler::handle_input(ACE_HANDLE)");
+
+ ACE_INET_Addr clientAddr;
+
+ // create a new ReadHandler
+ ReadHandler *reader = 0;
+ ACE_NEW_NORETURN (reader, ReadHandler());
+ if (reader == 0)
+ ACE_ERROR_RETURN((LM_ERROR, ACE_TEXT("%N:%l: Failed to allocate ")
+ ACE_TEXT ("reader. (errno = %i: %m)\n"), errno), -1);
+
+ // put reader in an auto pointer so we can use ACE_ERROR_RETURN safely
+ auto_ptr<ReadHandler> pReader(reader);
+
+ // accept the connection using the reader's stream
+ if (mAcceptor.accept(reader->getStream(), &clientAddr) == -1)
+ ACE_ERROR_RETURN((LM_ERROR, ACE_TEXT("%N:%l: Failed to accept ")
+ ACE_TEXT ("client connection. (errno = %i: %m)\n"), errno), -1);
+
+ // register the reader with the reactor
+ if (mReactor->register_handler(reader,
+ ACE_Event_Handler::READ_MASK) == -1)
+ ACE_ERROR_RETURN((LM_ERROR, ACE_TEXT("%N:%l: Failed to register ")
+ ACE_TEXT ("read handler. (errno = %i: %m)\n"), errno), -1);
+
+ // from now on the read handler takes care of itself
+ pReader.release();
+
+ return 0; // keep going
+}
+
+int AcceptHandler::handle_close(ACE_HANDLE, ACE_Reactor_Mask) {
+ ACE_TRACE("AcceptHandler::handle_close(ACE_HANDLE, ACE_Reactor_Mask)");
+
+ // close the listening socket
+ if (mAcceptor.close() == -1)
+ ACE_ERROR((LM_ERROR, ACE_TEXT("%N:%l: Failed to close the ")
+ ACE_TEXT ("socket. (errno = %i: %m)\n"), errno));
+
+ // no need to distinguish between error during close and normal close
+ // since ACE does not evaluate the return value of handle_close()
+
+ delete this;
+ return 0;
+}
+
diff --git a/ACE/examples/Reactor/TP_Reactor/AcceptHandler.h b/ACE/examples/Reactor/TP_Reactor/AcceptHandler.h
new file mode 100644
index 00000000000..036f7a36f5a
--- /dev/null
+++ b/ACE/examples/Reactor/TP_Reactor/AcceptHandler.h
@@ -0,0 +1,75 @@
+/*
+ * ACE reactor demonstration
+ *
+ * $Id$
+ * Date: 26-Jan-2006
+ */
+
+#ifndef __ACCEPTHANDLER_H__
+#define __ACCEPTHANDLER_H__
+
+#include <ace/Event_Handler.h>
+#include <ace/Reactor.h>
+#include <ace/SOCK_Acceptor.h>
+
+/**
+ * This accept handler is based on the provided solution from the ACE course.
+ */
+class AcceptHandler : public ACE_Event_Handler {
+
+ private:
+
+ /**
+ * The reactor to which the accept handler belongs.
+ */
+ ACE_Reactor *mReactor;
+
+ /**
+ * The socket used for incoming conections.
+ */
+ ACE_SOCK_Acceptor mAcceptor;
+
+ public:
+
+ /**
+ * @param reactor The reactor which will use this accept handler.
+ */
+ AcceptHandler(ACE_Reactor *reactor = 0);
+
+ /**
+ * The destructor exists for tracing purposes.
+ */
+ virtual ~AcceptHandler();
+
+ /**
+ * Open the listening socket and register the handler with the reactor.
+ *
+ * @return 0 on success, -1 on failure
+ */
+ int open(void);
+
+ /**
+ * @name Overridden methods from the ACE_Event_Handler
+ */
+ // @{
+
+ /**
+ * Provides the handle of mAcceptor.
+ */
+ virtual ACE_HANDLE get_handle(void) const;
+
+ /**
+ * Create a read handler for the new connection and register that
+ * handler with the reactor.
+ */
+ virtual int handle_input(ACE_HANDLE = ACE_INVALID_HANDLE);
+
+ /**
+ * Close the listening socket.
+ */
+ virtual int handle_close(ACE_HANDLE, ACE_Reactor_Mask);
+ // @}
+};
+
+#endif /* __ACCEPTHANDLER_H__ */
+
diff --git a/ACE/examples/Reactor/TP_Reactor/Makefile.am b/ACE/examples/Reactor/TP_Reactor/Makefile.am
new file mode 100644
index 00000000000..5407cbb10e1
--- /dev/null
+++ b/ACE/examples/Reactor/TP_Reactor/Makefile.am
@@ -0,0 +1,53 @@
+## Process this file with automake to create Makefile.in
+##
+## $Id$
+##
+## This file was generated by MPC. Any changes made directly to
+## this file will be lost the next time it is generated.
+##
+## MPC Command:
+## /acebuilds/ACE_wrappers-repository/bin/mwc.pl -include /acebuilds/MPC/config -include /acebuilds/MPC/templates -feature_file /acebuilds/ACE_wrappers-repository/local.features -noreldefs -type automake -exclude build,Kokyu
+
+ACE_BUILDDIR = $(top_builddir)
+ACE_ROOT = $(top_srcdir)
+
+## Makefile.TP_Reactor_Client.am
+noinst_PROGRAMS = client
+
+client_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+client_SOURCES = \
+ client.cpp \
+ AcceptHandler.h \
+ ReadHandler.h \
+ common.h
+
+client_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Makefile.TP_Reactor_Server.am
+noinst_PROGRAMS += server
+
+server_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+server_SOURCES = \
+ AcceptHandler.cpp \
+ ReadHandler.cpp \
+ server.cpp \
+ AcceptHandler.h \
+ ReadHandler.h
+
+server_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Clean up template repositories, etc.
+clean-local:
+ -rm -f *~ *.bak *.rpo *.sym lib*.*_pure_* core core.*
+ -rm -f gcctemp.c gcctemp so_locations *.ics
+ -rm -rf cxx_repository ptrepository ti_files
+ -rm -rf templateregistry ir.out
+ -rm -rf ptrepository SunWS_cache Templates.DB
diff --git a/ACE/examples/Reactor/TP_Reactor/README b/ACE/examples/Reactor/TP_Reactor/README
new file mode 100644
index 00000000000..32fbc15aca9
--- /dev/null
+++ b/ACE/examples/Reactor/TP_Reactor/README
@@ -0,0 +1,86 @@
+ACE reactor demonstration
+=========================
+
+Martin Kolleck
+Tino Riethmuller
+
+
+
+1. Introduction
+
+This program demonstrates what we think is a bug in the ACE library. The
+affected component is the ACE_TP_Reactor. According to the documentation, the
+reactor ensures that only one of the handle_*() methods of an event handler is
+called at a time. Tino found this to be not true and I wrote this example
+program showing the behavior. I do not exclude the possibility that we are
+using the ACE library in an unintended/wrong way. So comments on the code as
+well as any other remarks are welcome.
+
+
+
+2. The program
+
+The program consists of a client and a server. The general implementation is
+taken from the example solution to exercise 4c of the ACE course. The client
+will send a request to the server. This request is interpreted to be the size
+of the following data. The server allocates the memory required to hold the
+client's data and then sends a confirmation to the client, that it may
+proceed. The the client sends the large data chunk and the server again
+confirms it.
+
+The client runs in a loop which can be configured to run indefinitely or a
+previously set amount of times. The configuration i done from the command
+line. To invoke the client type:
+
+ $ ./client size [count]
+
+<size> sets the size (in MiB) of the buffer sent to the server. Depending on
+the systems, values between 60 and 100 have been used for testing. <count>
+determines how often the buffer is sent. If left out, the clients send the
+buffer until interrupted.
+
+The server is started without arguments. Both programs will print a dot for
+each successful connection. I found this an easy and unintrusive way of showing
+progress whithout flooding the console too fast. This also makes it easier to
+see when an error has occurred.
+
+
+
+3. Building the program
+
+This example was created on a Linux box. You will need the environment
+variable ACE_ROOT set up to the location where ACE is installed. It might be
+possible, that the path where the ACE libraries are found, needs to be adjusted
+in the Makefile.
+
+To compile simply type 'make' on the command prompt.
+
+ $ make
+
+This will create two executable files. One for the server and one for the
+client. (named respectively)
+
+
+
+4. Running the program
+
+The error seems to be of statistical nature. Occurring only under certain
+conditions (which I am not sure of, what they are). I successfully produced
+the error on the four machines given below (architecture, ACE and compiler
+version). I tested the program with localhost connections, as well as over
+a real network connection and could always reproduce the error.
+
+To detect the error I introduced a member variable to the read event handler.
+This counter is initialized to zero in the constructor. When handle_input() of
+the event handler is called, the counter is increased and decreased, when
+handle_input() returns. Before increasing the counter, It is compared to zero
+(which it should alway be, if only one invocation to handle_input() is made
+at a time) and an error message is printed if it is not zero.
+
+To test for the error, I ran one instance of the server program and TWO
+instances of the client program. The sizes of the buffers were between 60 and
+100 MiB and no count was given (running until stopped) The three Linux boxes
+showed the error within one minute of starting both clients. For the Windows
+box I decreased the buffer size to 15 and 20 MiB (Windows does not seem to have
+very performant localhost connectivity) and it took about half an
+hour until the error occurred the first time.
diff --git a/ACE/examples/Reactor/TP_Reactor/ReadHandler.cpp b/ACE/examples/Reactor/TP_Reactor/ReadHandler.cpp
new file mode 100644
index 00000000000..06c6c953046
--- /dev/null
+++ b/ACE/examples/Reactor/TP_Reactor/ReadHandler.cpp
@@ -0,0 +1,151 @@
+/*
+ * ACE reactor demonstration
+ *
+ * $Id$
+ * Date: 26-Jan-2006
+ */
+
+#include <ace/streams.h>
+#include <ace/Time_Value.h>
+
+#include "common.h"
+#include "ReadHandler.h"
+
+/**
+ * This macro is used to increase the invocation counter by one when entering
+ * handle_input(). It also checks wether the counter is greater than zero
+ * indicating, that handle_input() has been called before.
+ */
+#define INVOCATION_ENTER() do { if (mInvocationCounter > 0) \
+ ACE_ERROR((LM_ERROR, ACE_TEXT("Multiple invocations detected.\n"))); \
+ mInvocationCounter++; } while (0)
+
+/**
+ * THis macro is the counter part to INVOCATION_ENTER(). It decreases the
+ * invocation counter and then returns the given value. This macro is
+ * here for convenience to decrease the invocation counter also when returning
+ * due to errors.
+ */
+#define INVOCATION_RETURN(retval) do { mInvocationCounter--; \
+ return retval; } while(0)
+
+ReadHandler::ReadHandler() : ACE_Event_Handler(), mStream(), mDataSize(0),
+ mData(0), mCallCounter(0), mInvocationCounter(0) {
+ ACE_TRACE(ACE_TEXT("ReadHandler::ReadHandler()"));
+}
+
+ReadHandler::~ReadHandler() {
+ ACE_TRACE(ACE_TEXT("ReadHandler::~ReadHandler()"));
+
+ if (mStream.close() == -1)
+ ACE_ERROR((LM_ERROR, ACE_TEXT("%N:%l: Failed to close socket. ")
+ ACE_TEXT ("(errno = %i: %m)\n"), errno));
+
+ delete[] mData;
+}
+
+ACE_SOCK_Stream &ReadHandler::getStream(void) {
+ ACE_TRACE(ACE_TEXT("ReadHandler::getStream(void)"));
+ return mStream;
+}
+
+ACE_HANDLE ReadHandler::get_handle(void) const {
+ ACE_TRACE(ACE_TEXT("ReadHandler::get_handle(void)"));
+ return mStream.get_handle();
+}
+
+int ReadHandler::handle_input(ACE_HANDLE) {
+ ACE_TRACE(ACE_TEXT("ReadHandler::handle_input(ACE_HANDLE)"));
+
+ INVOCATION_ENTER();
+
+ // the response sent to the client
+ char response = 0;
+
+ if (mCallCounter == 0) {
+
+ /*
+ * This is the first request from the client.
+ */
+
+ // increase the call counter so the next client request goes to else-if
+ mCallCounter++;
+
+ // get the desired size from the client
+ // Note: only use the sizeof and pointer to int on compatible
+ // platforms (i.e. little-endian/big-endian, data type size)
+ if (mStream.recv_n(&mDataSize, sizeof(mDataSize),
+ &connTimeout) != sizeof(mDataSize)) {
+ ACE_ERROR((LM_ERROR, ACE_TEXT("%N:%l: Failed to receive ")
+ ACE_TEXT ("request. (errno = %i: %m)\n"), errno));
+ INVOCATION_RETURN(-1);
+ }
+
+ // The verbose debug output is replaced with some unintrusive dots.
+ // This increases visibility of the desired effect.
+ // ACE_DEBUG((LM_DEBUG, ACE_TEXT("%@: Data size: %i\n"), this, mDataSize));
+ ACE_DEBUG((LM_DEBUG, ACE_TEXT(".")));
+
+ // check mDataSize for plausability then allocate memory
+ if (mDataSize > 0) {
+ mData = new (std::nothrow) char[mDataSize];
+ if (mData == 0)
+ ACE_DEBUG((LM_DEBUG, ACE_TEXT("%N:%l: Failed to allocate ")
+ ACE_TEXT ("data buffer.\n")));
+ else
+ response = 'K';
+ }
+
+ // send the response to the client (which is still 0, if the
+ // allocation did not succeed)
+ if (mStream.send_n(&response, sizeof(response), &connTimeout) != 1) {
+ ACE_ERROR((LM_ERROR, ACE_TEXT("%N:%l: Failed to send ")
+ ACE_TEXT ("response. (errno = %i: %m)\n"), errno));
+ INVOCATION_RETURN(-1);
+ }
+
+ if (response == 'K')
+ INVOCATION_RETURN(0); // get another request from the same client
+ else
+ INVOCATION_RETURN(-1); // the client will not send data if response != 'K'
+
+ } else if (mCallCounter == 1) {
+
+ /*
+ * This is the second request from the client.
+ */
+
+ // increase the call counter, this read handler should not be called
+ // again
+ mCallCounter++;
+
+ // receive the data from the client
+ if (mStream.recv_n(mData, mDataSize, &connTimeout) != mDataSize) {
+ ACE_ERROR((LM_ERROR, ACE_TEXT("%N:%l: Failed to receive data.")
+ ACE_TEXT ("(errno = %i: %m)\n"), errno));
+ INVOCATION_RETURN(-1);
+ }
+
+ response = 'K';
+
+ if (mStream.send_n(&response, 1, &connTimeout) != 1) {
+ ACE_ERROR((LM_ERROR, ACE_TEXT("%N:%l: Failed to send ")
+ ACE_TEXT ("confirmation. (errno = %i: %m)\n"), errno));
+ INVOCATION_RETURN(-1);
+ }
+
+ INVOCATION_RETURN(-1); // ask for removal, since client does not send any more data
+ }
+
+ // this is to find strange actions with the call counter
+ ACE_ERROR((LM_ERROR, ACE_TEXT("%N:%l: We should not get here.")));
+ INVOCATION_RETURN(-1);
+}
+
+int ReadHandler::handle_close(ACE_HANDLE, ACE_Reactor_Mask) {
+ ACE_TRACE("ReadHandler::handle_close(ACE_HANDLE, ACE_Reactor_Mask)");
+
+ delete this;
+ return 0;
+}
+
diff --git a/ACE/examples/Reactor/TP_Reactor/ReadHandler.h b/ACE/examples/Reactor/TP_Reactor/ReadHandler.h
new file mode 100644
index 00000000000..41d58b6008a
--- /dev/null
+++ b/ACE/examples/Reactor/TP_Reactor/ReadHandler.h
@@ -0,0 +1,92 @@
+/*
+ * ACE reactor demonstration
+ *
+ * $Id$
+ * Date: 26-Jan-2006
+ */
+
+#ifndef __READHANDLER_H__
+#define __READHANDLER_H__
+
+#include <ace/Event_Handler.h>
+#include <ace/SOCK_Stream.h>
+
+/**
+ * This read handler is created by the accept handler and handles all the data
+ * exchange between client and server. The client makes two requests to the
+ * server. The first asks the server to create a buffer which will hold the
+ * data sent in the second call.
+ */
+class ReadHandler : public ACE_Event_Handler {
+
+ private:
+
+ /**
+ * The stream socket used for data exchange.
+ */
+ ACE_SOCK_Stream mStream;
+
+ /**
+ * The size of the data array.
+ */
+ int mDataSize;
+
+ /**
+ * The array containing the client's data.
+ */
+ char *mData;
+
+ /**
+ * The call counter to distinguish between first and second call.
+ */
+ int mCallCounter;
+
+ /**
+ * Count the numer of invocations of handle_*(). According to the
+ * docs, there should be only one invocation at any given time.
+ */
+ int mInvocationCounter;
+
+ public:
+
+ /**
+ * Initialization.
+ */
+ ReadHandler(void);
+
+ /**
+ * Clean up data.
+ */
+ virtual ~ReadHandler();
+
+ /**
+ * Provide access to the internal stream socket.
+ */
+ ACE_SOCK_Stream &getStream(void);
+
+ /**
+ * @name Overridden methods from the ACE_Event_Handler
+ */
+ // @{
+
+ /**
+ * Provides the handle of mStream;
+ */
+ virtual ACE_HANDLE get_handle(void) const;
+
+ /**
+ * Handles the data excahnge between client and server. On the first
+ * invocation, mData is allocated to the requested size and on the
+ * second invocation, that buffer is filled with the client's data.
+ */
+ virtual int handle_input(ACE_HANDLE = ACE_INVALID_HANDLE);
+
+ /**
+ * Deletes this instance of the read handler.
+ */
+ virtual int handle_close(ACE_HANDLE, ACE_Reactor_Mask);
+ // @}
+};
+
+#endif /* __READHANDLER_H__ */
+
diff --git a/ACE/examples/Reactor/TP_Reactor/TP_Reactor.mpc b/ACE/examples/Reactor/TP_Reactor/TP_Reactor.mpc
new file mode 100644
index 00000000000..03d8de2e7aa
--- /dev/null
+++ b/ACE/examples/Reactor/TP_Reactor/TP_Reactor.mpc
@@ -0,0 +1,18 @@
+// -*- MPC -*-
+// $Id$
+
+project (*client) : aceexe {
+ exename = client
+ Source_Files {
+ client.cpp
+ }
+}
+
+project (*server) : aceexe {
+ exename = server
+ Source_Files {
+ server.cpp
+ AcceptHandler.cpp
+ ReadHandler.cpp
+ }
+}
diff --git a/ACE/examples/Reactor/TP_Reactor/client.cpp b/ACE/examples/Reactor/TP_Reactor/client.cpp
new file mode 100644
index 00000000000..509f2e9c457
--- /dev/null
+++ b/ACE/examples/Reactor/TP_Reactor/client.cpp
@@ -0,0 +1,141 @@
+/*
+ * ACE reactor demonstration
+ *
+ * $Id$
+ * Date: 26-Jan-2006
+ */
+
+#include <ace/Auto_Ptr.h>
+#include <ace/INET_Addr.h>
+#include <ace/Log_Msg.h>
+#include <ace/OS.h>
+#include <ace/SOCK_Acceptor.h>
+#include <ace/SOCK_Connector.h>
+#include <ace/SOCK_Stream.h>
+#include <ace/streams.h>
+
+#include "common.h"
+
+/**
+ * Print usage information for the client.
+ *
+ * @param arg The progams name (argv[0]).
+ */
+int printUsage(ACE_TCHAR *arg) {
+ cerr << "Usage: " << arg << " size [count]" << endl;
+ cerr << "\tSends <size> MiB to the server and optionally repeats that "
+ << "<count> times." << endl;
+ cerr << "\tAll arguments must be positive numbers. If no <count> is "
+ << "given, the\n\tclient runs until interrupted." << endl;
+ return -1;
+}
+
+int ACE_TMAIN(int argc, ACE_TCHAR **argv) {
+
+ // size and count for transmissions
+ int size = 0, count = -1;
+
+ // the server's answer is a single byte
+ char answer;
+
+ // parse the <size> argument
+ if ((argc < 2) || (((size = ACE_OS::strtol(argv[1], 0, 10)) < 1) ||
+ (errno == EINVAL)))
+ return printUsage(argv[0]);
+
+ // take size as the number of MiB and create appropriate buffer
+ size *= BASE;
+ char *someData = new (std::nothrow) char[size];
+
+ if (someData == 0)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%N:%l: Failed to allocate ")
+ ACE_TEXT ("data buffer.\n")), -1);
+
+ // put someData in an auto_ptr so it gets deleted automatically
+ auto_ptr<char> pSomeData(someData);
+
+ // parse the <count> argument if available
+ if ((argc == 3) && (((count = ACE_OS::strtol(argv[2], 0, 10)) < 1) ||
+ (errno == EINVAL)))
+ return printUsage(argv[0]);
+
+ // the server listens on localhost on default port (from common.h)
+ ACE_INET_Addr serverAddr(PORT, "localhost");
+
+ ACE_SOCK_Stream stream;
+ ACE_SOCK_Connector connector;
+
+ // -1 is running indefinitely
+ while ((count == -1) || (count-- != 0)) {
+
+ // some output, that we know something is happening
+ //ACE_DEBUG((LM_DEBUG, ACE_TEXT("%N:%l: Passes left: %i\n"), count));
+ ACE_DEBUG((LM_DEBUG, ACE_TEXT(".")));
+
+ // connect to the server and get the stream
+ if (connector.connect(stream, serverAddr) == -1) {
+ ACE_ERROR((LM_ERROR,
+ ACE_TEXT("%N:%l: Failed to connect to ")
+ ACE_TEXT ("server. (errno = %i: %m)\n"), errno));
+ break;
+ }
+
+ try {
+
+ // send the request to the server (number of MiB in the next call)
+ // Note: only use the sizeof and pointer to int on compatible
+ // platforms (i.e. little-endian/big-endian, data type size)
+ if (stream.send_n(&size, sizeof(size), &connTimeout) != sizeof(size)) {
+ ACE_ERROR((LM_ERROR, ACE_TEXT("%N:%l: Failed to send ")
+ ACE_TEXT ("request. (errno = %i: %m)\n"), errno));
+ throw(1);
+ }
+
+ // receive the answer
+ if (stream.recv_n(&answer, sizeof(answer), &connTimeout) != 1) {
+ ACE_ERROR((LM_ERROR, ACE_TEXT("%N: %l: Failed to receive ")
+ ACE_TEXT ("1st response. (errno = %i: %m)\n"), errno));
+ throw(1);
+ }
+
+ // server answer, 'K" indicates a positive answer
+ if (answer == 'K') {
+
+ // send a huge message to the server
+ if (stream.send_n(someData, size, &connTimeout) != size) {
+ ACE_ERROR((LM_ERROR, ACE_TEXT("%N:%l: Failed to send ")
+ ACE_TEXT ("someData. (errno = %i: %m)\n"), errno));
+ throw(1);
+ }
+
+ // get an answer
+ if (stream.recv_n(&answer, sizeof(answer), &connTimeout) != 1) {
+ ACE_ERROR((LM_ERROR, ACE_TEXT("%N: %l: Failed to receive ")
+ ACE_TEXT ("2nd response. (errno = %i: %m)\n"), errno));
+ throw(1);
+ }
+
+ // check the answer
+ if (answer != 'K') {
+ cout << "The server was unable to process the data."
+ << endl;
+ }
+ }
+ } catch (...) {
+ // ok we know an error occurred, we need to close the socket.
+ // The we'll try again.
+ }
+
+ // close the current stream
+ if (stream.close() == -1) {
+ ACE_ERROR((LM_ERROR, ACE_TEXT("%N:%l: Failed to close ")
+ ACE_TEXT ("socket. (errno = %i: %m)\n"), errno));
+ break;
+ }
+ } // while
+
+ cout << "Bye. Bye" << endl;
+ return 0;
+}
+
diff --git a/ACE/examples/Reactor/TP_Reactor/common.h b/ACE/examples/Reactor/TP_Reactor/common.h
new file mode 100644
index 00000000000..c9661027923
--- /dev/null
+++ b/ACE/examples/Reactor/TP_Reactor/common.h
@@ -0,0 +1,29 @@
+/*
+ * ACE reactor demonstration
+ *
+ * $Id$
+ * Date: 26-Jan-2006
+ */
+
+#ifndef __COMMON_H__
+#define __COMMON_H__
+
+#include <ace/Time_Value.h>
+
+/**
+ * The port number used by client and server.
+ */
+static const int PORT = 4711;
+
+/**
+ * The base size. 0x100000 = 1 MiB
+ */
+static const int BASE = 0x100000;
+
+/**
+ * The timeout value for connections. (30 seconds)
+ */
+static const ACE_Time_Value connTimeout(30);
+
+#endif /* __COMMON_H__ */
+
diff --git a/ACE/examples/Reactor/TP_Reactor/run_test.pl b/ACE/examples/Reactor/TP_Reactor/run_test.pl
new file mode 100644
index 00000000000..ac07295a735
--- /dev/null
+++ b/ACE/examples/Reactor/TP_Reactor/run_test.pl
@@ -0,0 +1,41 @@
+eval '(exit $?0)' && eval 'exec perl -S $0 ${1+"$@"}'
+ & eval 'exec perl -S $0 $argv:q'
+ if 0;
+
+# $Id$
+# -*- perl -*-
+
+use lib '../../../bin';
+use PerlACE::Run_Test;
+
+$status = 0;
+
+$SV = new PerlACE::Process ("server", "");
+$CL1 = new PerlACE::Process ("client", "80 100");
+$CL2 = new PerlACE::Process ("client", "80 100");
+$SV->Spawn ();
+
+sleep (1);
+
+$client1 = $CL1->Spawn ();
+
+if ($client1 != 0) {
+ print STDERR "ERROR: client 1 returned $client1\n";
+ $status = 1;
+}
+
+$client2 = $CL2->Spawn ();
+
+if ($client2 != 0) {
+ print STDERR "ERROR: client 2 returned $client2\n";
+ $status = 1;
+}
+
+$server = $SV->WaitKill (1000);
+
+if ($server != 0) {
+ print STDERR "ERROR: server returned $server\n";
+ $status = 1;
+}
+
+exit $status;
diff --git a/ACE/examples/Reactor/TP_Reactor/server.cpp b/ACE/examples/Reactor/TP_Reactor/server.cpp
new file mode 100644
index 00000000000..0c147818424
--- /dev/null
+++ b/ACE/examples/Reactor/TP_Reactor/server.cpp
@@ -0,0 +1,66 @@
+/*
+ * ACE reactor demonstration
+ *
+ * $Id$
+ * Date: 26-Jan-2006
+ */
+
+#include <ace/Event_Handler.h>
+#include <ace/Log_Msg.h>
+#include <ace/OS.h>
+#include <ace/Reactor.h>
+#include <ace/Signal.h>
+#include <ace/streams.h>
+#include <ace/Thread_Manager.h>
+#include <ace/TP_Reactor.h>
+
+#include "AcceptHandler.h"
+
+/**
+ * This is the function run by all threads in the thread pool.
+ *
+ * @param arg is expected to be of type (ACE_Reactor *)
+ */
+ACE_THR_FUNC_RETURN threadFunc(void *arg) {
+ ACE_TRACE("threadFunc(void *)");
+
+ ACE_Reactor *reactor = (ACE_Reactor *) arg;
+ reactor->run_reactor_event_loop();
+
+ return 0;
+}
+
+/**
+ * The main function sets up the TP reactor. The code is basically taken from
+ * the solution to exercise 4c of the ACE course.
+ */
+int ACE_TMAIN(int, ACE_TCHAR **) {
+
+ // create a reactor from a TP reactor
+ ACE_TP_Reactor tpReactor;
+ ACE_Reactor reactor(&tpReactor);
+
+ // create a new accept handler using that reactor
+ AcceptHandler *acceptHandler = 0;
+ ACE_NEW_NORETURN (acceptHandler, AcceptHandler(&reactor));
+ if (acceptHandler == 0)
+ ACE_ERROR_RETURN((LM_ERROR, ACE_TEXT("%N:%l: Failed to allocate ")
+ ACE_TEXT ("accept handler. (errno = %i: %m)\n"), errno), -1);
+
+ // open the accept handler
+ if (acceptHandler->open() == -1) {
+ delete acceptHandler;
+ ACE_ERROR_RETURN((LM_ERROR, ACE_TEXT("%N:%l: Failed to open accept ")
+ ACE_TEXT ("handler. Exiting.\n")), -1);
+ }
+
+ // spawn some threads which run the reactor event loop(s)
+ ACE_Thread_Manager::instance()->spawn_n(9, threadFunc, &reactor);
+
+ // let the thread manager wait for all threads
+ ACE_Thread_Manager::instance()->wait();
+
+ ACE_DEBUG((LM_DEBUG, ACE_TEXT("Bye. Bye.\n")));
+ return 0;
+}
+
diff --git a/ACE/examples/Reactor/WFMO_Reactor/APC.cpp b/ACE/examples/Reactor/WFMO_Reactor/APC.cpp
new file mode 100644
index 00000000000..bf42fd1edfa
--- /dev/null
+++ b/ACE/examples/Reactor/WFMO_Reactor/APC.cpp
@@ -0,0 +1,124 @@
+// $Id$
+
+// ============================================================================
+//
+// = LIBRARY
+// examples
+//
+// = FILENAME
+// APC.cpp
+//
+// = DESCRIPTION
+//
+// Tests the WFMO_Reactor's ability to handle regular APC
+// notifications.
+//
+// = AUTHOR
+//
+// Irfan Pyarali <irfan@cs.wustl.edu>
+//
+// ============================================================================
+
+#include "ace/OS_main.h"
+
+#if defined (ACE_WIN32)
+
+#include "ace/Reactor.h"
+#include "ace/Auto_Event.h"
+
+ACE_RCSID(WFMO_Reactor, APC, "$Id$")
+
+class Event_Handler : public ACE_Event_Handler
+{
+public:
+ int handle_signal (int signum,
+ siginfo_t * = 0,
+ ucontext_t * = 0);
+
+ int handle_timeout (const ACE_Time_Value &tv,
+ const void *arg = 0);
+
+ ACE_Auto_Event handle_;
+ int iterations_;
+};
+
+static Event_Handler *global_event_handler;
+
+static void WINAPI
+apc_callback (DWORD)
+{
+ ACE_DEBUG ((LM_DEBUG,
+ "(%t) apc occured @ %T\n"));
+
+ global_event_handler->handle_.signal ();
+}
+
+void
+queue_apc (void)
+{
+ DWORD result = ::QueueUserAPC (reinterpret_cast<PAPCFUNC> (&apc_callback),
+ // pointer to APC function
+ ::GetCurrentThread (), // handle to the thread
+ 0); // argument for the APC function
+ if (result == FALSE)
+ ACE_OS::exit (-1);
+}
+
+int
+Event_Handler::handle_signal (int,
+ siginfo_t *,
+ ucontext_t *)
+{
+ --this->iterations_;
+
+ if (this->iterations_ == 0)
+ {
+ ACE_Reactor::instance ()->remove_handler (this->handle_.handle (),
+ ACE_Event_Handler::DONT_CALL);
+ ACE_Reactor::end_event_loop ();
+ }
+
+ return 0;
+}
+
+int
+Event_Handler::handle_timeout (const ACE_Time_Value &,
+ const void *)
+{
+ ACE_DEBUG ((LM_DEBUG,
+ "(%t) timeout occured @ %T\n"));
+ queue_apc ();
+ return 0;
+}
+
+int
+ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ Event_Handler event_handler;
+ event_handler.iterations_ = 5;
+ global_event_handler = &event_handler;
+
+ int result = ACE_Reactor::instance ()->register_handler (&event_handler,
+ event_handler.handle_.handle ());
+ ACE_ASSERT (result == 0);
+
+ ACE_Time_Value timeout (2);
+ result = ACE_Reactor::instance ()->schedule_timer (&event_handler,
+ 0,
+ timeout,
+ timeout);
+ ACE_ASSERT (result != -1);
+
+ ACE_Reactor::run_alertable_event_loop ();
+
+ ACE_Reactor::instance ()->cancel_timer(&event_handler);
+
+ return 0;
+}
+#else /* !ACE_WIN32 */
+int
+ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ return 0;
+}
+#endif /* ACE_WIN32 */
diff --git a/ACE/examples/Reactor/WFMO_Reactor/Abandoned.cpp b/ACE/examples/Reactor/WFMO_Reactor/Abandoned.cpp
new file mode 100644
index 00000000000..c860fc2810c
--- /dev/null
+++ b/ACE/examples/Reactor/WFMO_Reactor/Abandoned.cpp
@@ -0,0 +1,141 @@
+// $Id$
+
+// ============================================================================
+//
+// = LIBRARY
+// examples
+//
+// = FILENAME
+// Abandoned.cpp
+//
+// = DESCRIPTION
+//
+// Tests the WFMO_Reactor's ability to handle abandoned mutexes.
+//
+// = AUTHOR
+//
+// Irfan Pyarali <irfan@cs.wustl.edu>
+//
+// ============================================================================
+
+#include "ace/OS_main.h"
+
+#if defined (ACE_WIN32)
+
+#include "ace/Reactor.h"
+#include "ace/Thread_Manager.h"
+#include "ace/Process_Mutex.h"
+#include "ace/Auto_Event.h"
+
+ACE_RCSID(WFMO_Reactor, Abandoned, "$Id$")
+
+class Event_Handler : public ACE_Event_Handler
+{
+public:
+ int handle_signal (int signum,
+ siginfo_t * = 0,
+ ucontext_t * = 0);
+
+ int handle_timeout (const ACE_Time_Value &tv,
+ const void *arg = 0);
+
+ ACE_Auto_Event handle_;
+ ACE_Process_Mutex *mutex_;
+ int iterations_;
+};
+
+static int abandon = 1;
+
+static ACE_THR_FUNC_RETURN
+worker (void *data)
+{
+ Event_Handler *handler = (Event_Handler *) data;
+
+ handler->handle_.signal ();
+ handler->mutex_->acquire ();
+
+ if (!abandon)
+ handler->mutex_->release ();
+
+ return 0;
+}
+
+int
+Event_Handler::handle_signal (int,
+ siginfo_t *s,
+ ucontext_t *)
+{
+ ACE_HANDLE handle = s->si_handle_;
+ if (handle == this->handle_.handle ())
+ ACE_Reactor::instance ()->register_handler (this,
+ this->mutex_->lock ().proc_mutex_);
+ else
+ {
+ ACE_Reactor::instance ()->remove_handler (this->mutex_->lock ().proc_mutex_,
+ ACE_Event_Handler::DONT_CALL);
+ delete this->mutex_;
+ }
+
+ return 0;
+}
+
+int
+Event_Handler::handle_timeout (const ACE_Time_Value &,
+ const void *)
+{
+ --this->iterations_;
+ ACE_DEBUG ((LM_DEBUG,
+ "(%t) timeout occured @ %T, iterations left %d\n",
+ this->iterations_));
+
+ if (this->iterations_ == 0)
+ {
+ ACE_Reactor::instance ()->remove_handler (this->handle_.handle (),
+ ACE_Event_Handler::DONT_CALL);
+
+ ACE_Reactor::instance ()->cancel_timer (this);
+
+ ACE_Reactor::end_event_loop ();
+ }
+ else
+ {
+ ACE_NEW_RETURN (this->mutex_,
+ ACE_Process_Mutex,
+ -1);
+ int result = ACE_Thread_Manager::instance ()->spawn (&worker, this);
+ ACE_ASSERT (result != -1);
+ ACE_UNUSED_ARG (result);
+ }
+
+ return 0;
+}
+
+int
+ACE_TMAIN (int , ACE_TCHAR *[])
+{
+ Event_Handler event_handler;
+
+ event_handler.iterations_ = 5;
+ int result = ACE_Reactor::instance ()->register_handler
+ (&event_handler,
+ event_handler.handle_.handle ());
+ ACE_ASSERT (result == 0);
+
+ ACE_Time_Value timeout (2);
+ result = ACE_Reactor::instance ()->schedule_timer (&event_handler,
+ 0,
+ timeout,
+ timeout);
+ ACE_ASSERT (result != -1);
+
+ ACE_Reactor::run_event_loop ();
+
+ return 0;
+}
+#else /* !ACE_WIN32 */
+int
+ACE_TMAIN (int , ACE_TCHAR *[])
+{
+ return 0;
+}
+#endif /* ACE_WIN32 */
diff --git a/ACE/examples/Reactor/WFMO_Reactor/Console_Input.cpp b/ACE/examples/Reactor/WFMO_Reactor/Console_Input.cpp
new file mode 100644
index 00000000000..363a6a8ead8
--- /dev/null
+++ b/ACE/examples/Reactor/WFMO_Reactor/Console_Input.cpp
@@ -0,0 +1,87 @@
+// $Id$
+
+// ============================================================================
+//
+// = LIBRARY
+// examples
+//
+// = FILENAME
+// Console_Input.cpp
+//
+// = DESCRIPTION
+//
+// This application tests the working of WFMO_Reactor when users
+// are interested in console input.
+//
+// = AUTHOR
+// Irfan Pyarali <irfan@cs.wustl.edu>
+//
+// ============================================================================
+
+#include "ace/Reactor.h"
+#include "ace/OS_NS_unistd.h"
+#include "ace/OS_NS_string.h"
+#include "ace/OS_main.h"
+
+ACE_RCSID(WFMO_Reactor, Console_Input, "$Id$")
+
+class Event_Handler : public ACE_Event_Handler
+{
+public:
+ Event_Handler (ACE_Reactor &reactor);
+ int handle_signal (int signum, siginfo_t * = 0, ucontext_t * = 0);
+ int handle_close (ACE_HANDLE handle,
+ ACE_Reactor_Mask close_mask);
+};
+
+Event_Handler::Event_Handler (ACE_Reactor &reactor)
+{
+ this->reactor (&reactor);
+
+ if (this->reactor ()->register_handler (this,
+ ACE_STDIN) != 0)
+ ACE_ERROR ((LM_ERROR,
+ "Registration with Reactor could not be done\n"));
+}
+
+int
+Event_Handler::handle_signal (int, siginfo_t *, ucontext_t *)
+{
+ ACE_TCHAR buffer[BUFSIZ];
+ int result = ACE_OS::read (ACE_STDIN, buffer, sizeof buffer);
+ buffer[result] = '\0';
+
+ if (result <= 0)
+ {
+ this->reactor ()->close ();
+ ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "ACE_OS::read"), -1);
+ }
+
+ if (ACE_OS::strcmp (ACE_TEXT("quit\r\n"), buffer) == 0)
+ this->reactor ()->close ();
+
+ ACE_DEBUG ((LM_DEBUG, "User input: %s", buffer));
+
+ return 0;
+}
+
+int
+Event_Handler::handle_close (ACE_HANDLE,
+ ACE_Reactor_Mask)
+{
+ ACE_DEBUG ((LM_DEBUG, "Event_Handler removed from Reactor\n"));
+ return 0;
+}
+
+int
+ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ ACE_Reactor reactor;
+ Event_Handler handler (reactor);
+
+ int result = 0;
+ while (result != -1)
+ result = reactor.handle_events ();
+
+ return 0;
+}
diff --git a/ACE/examples/Reactor/WFMO_Reactor/Directory_Changes.cpp b/ACE/examples/Reactor/WFMO_Reactor/Directory_Changes.cpp
new file mode 100644
index 00000000000..7f5126c6cba
--- /dev/null
+++ b/ACE/examples/Reactor/WFMO_Reactor/Directory_Changes.cpp
@@ -0,0 +1,128 @@
+// $Id$
+//
+// ============================================================================
+//
+// = LIBRARY
+// examples
+//
+// = FILENAME
+// Directory_Changes.cpp
+//
+// = DESCRIPTION
+//
+// This application tests the working of WFMO_Reactor when users
+// are interested in monitoring changes in the filesystem.
+//
+// = AUTHOR
+// Irfan Pyarali
+//
+// ============================================================================
+
+#include "ace/OS_main.h"
+
+#if defined (ACE_WIN32)
+
+#include "ace/Reactor.h"
+#include "ace/OS_NS_unistd.h"
+#include "ace/OS_NS_fcntl.h"
+
+ACE_RCSID(WFMO_Reactor, Directory_Changes, "$Id$")
+
+static int stop_test = 0;
+static const ACE_TCHAR *directory = ACE_TEXT (".");
+static const ACE_TCHAR *temp_file = ACE_TEXT ("foo");
+
+class Event_Handler : public ACE_Event_Handler
+{
+public:
+ Event_Handler (ACE_Reactor &reactor);
+ ~Event_Handler (void);
+ int handle_signal (int signum, siginfo_t * = 0, ucontext_t * = 0);
+ int handle_close (ACE_HANDLE handle,
+ ACE_Reactor_Mask close_mask);
+
+private:
+ ACE_HANDLE handle_;
+};
+
+Event_Handler::Event_Handler (ACE_Reactor &reactor)
+ : handle_ (ACE_INVALID_HANDLE)
+{
+ this->reactor (&reactor);
+
+ int change_notification_flags = FILE_NOTIFY_CHANGE_FILE_NAME;
+
+ this->handle_ = ACE_TEXT_FindFirstChangeNotification (directory, // pointer to name of directory to watch
+ FALSE, // flag for monitoring directory or directory tree
+ change_notification_flags // filter conditions to watch for
+ );
+ if (this->handle_ == ACE_INVALID_HANDLE)
+ ACE_ERROR ((LM_ERROR, "FindFirstChangeNotification could not be setup\n"));
+
+ if (this->reactor ()->register_handler (this,
+ this->handle_) != 0)
+ ACE_ERROR ((LM_ERROR, "Registration with Reactor could not be done\n"));
+}
+
+Event_Handler::~Event_Handler (void)
+{
+}
+
+int
+Event_Handler::handle_signal (int, siginfo_t *, ucontext_t *)
+{
+ ::FindNextChangeNotification (this->handle_);
+ if (stop_test)
+ this->reactor ()->close ();
+ return 0;
+}
+
+int
+Event_Handler::handle_close (ACE_HANDLE,
+ ACE_Reactor_Mask)
+{
+ ACE_DEBUG ((LM_DEBUG, "Event_Handler removed from Reactor\n"));
+ ::FindCloseChangeNotification (this->handle_);
+ return 0;
+}
+
+void
+worker (void)
+{
+ ACE_DEBUG ((LM_DEBUG, "(%t) Thread creation\n"));
+ ACE_DEBUG ((LM_DEBUG, "(%t) Thread creating temporary file\n"));
+ ACE_HANDLE file = ACE_OS::open (temp_file, _O_CREAT | _O_EXCL);
+ if (file == ACE_INVALID_HANDLE)
+ ACE_ERROR ((LM_ERROR, "Error in creating %s: %p\n", temp_file, "ACE_OS::open"));
+ else
+ {
+ ACE_OS::close (file);
+ ACE_DEBUG ((LM_DEBUG, "(%t) Thread sleeping\n"));
+ ACE_OS::sleep (3);
+ ACE_DEBUG ((LM_DEBUG, "(%t) Thread removing temporary file\n"));
+ stop_test = 1;
+ ACE_OS::unlink (temp_file);
+ }
+}
+
+int
+ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ ACE_Reactor reactor;
+ Event_Handler handler (reactor);
+
+ int result = ACE_OS::thr_create ((ACE_THR_FUNC) worker, 0, 0, 0);
+ ACE_ASSERT (result == 0);
+
+ for (result = 0; result != -1; result = reactor.handle_events ())
+ continue;
+
+ return 0;
+}
+#else /* !ACE_WIN32 */
+int
+ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ return 0;
+}
+#endif /* ACE_WIN32 */
diff --git a/ACE/examples/Reactor/WFMO_Reactor/Exceptions.cpp b/ACE/examples/Reactor/WFMO_Reactor/Exceptions.cpp
new file mode 100644
index 00000000000..5bbf0b4e4f3
--- /dev/null
+++ b/ACE/examples/Reactor/WFMO_Reactor/Exceptions.cpp
@@ -0,0 +1,109 @@
+// $Id$
+//
+// ============================================================================
+//
+// = LIBRARY
+// examples
+//
+// = FILENAME
+// Exceptions.cpp
+//
+// = DESCRIPTION
+//
+// This test application tests the state of WFMO_Reactor when
+// exceptions occurs when executing user callbacks.
+//
+// The thread count in WFMO_Reactor is used to ensure that state of
+// WFMO_Reactor is not fouled up when exceptions occur in user code.
+// This example also shows how to write event loops that survive
+// user exceptions
+//
+// = AUTHOR
+// Irfan Pyarali
+//
+// ============================================================================
+
+#include "ace/OS_main.h"
+
+#if defined (ACE_WIN32)
+
+#include "ace/WFMO_Reactor.h"
+
+ACE_RCSID(WFMO_Reactor, Exceptions, "$Id$")
+
+class Event_Handler : public ACE_Event_Handler
+{
+public:
+ Event_Handler (void)
+ : event_ (1)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ "Event_Handler created\n"));
+ }
+
+ ~Event_Handler (void)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ "Event_Handler destroyed\n"));
+ }
+
+ int handle_signal (int, siginfo_t * = 0, ucontext_t * = 0)
+ {
+ char *cause_exception = 0;
+ char a = *cause_exception;
+ ACE_UNUSED_ARG(a);
+ return 0;
+ }
+
+ ACE_HANDLE get_handle (void) const
+ {
+ return this->event_.handle ();
+ }
+private:
+ ACE_Manual_Event event_;
+};
+
+class ACE_WFMO_Reactor_Test
+{
+public:
+ static void doit (ACE_WFMO_Reactor &wfmo_reactor)
+ {
+ for (int i = 1; i <= 10; i++)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ "Active threads in WFMO_Reactor (before handle_events) = %d\n",
+ wfmo_reactor.active_threads_));
+ ACE_SEH_TRY
+ {
+ wfmo_reactor.handle_events ();
+ }
+ ACE_SEH_EXCEPT (EXCEPTION_EXECUTE_HANDLER)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ "Exception occurred\n"));
+ }
+ ACE_DEBUG ((LM_DEBUG,
+ "Active threads in WFMO_Reactor (after handle_events) = %d\n",
+ wfmo_reactor.active_threads_));
+ }
+ }
+};
+
+int
+ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ Event_Handler handler;
+ ACE_WFMO_Reactor wfmo_reactor;
+ wfmo_reactor.register_handler (&handler);
+
+ ACE_WFMO_Reactor_Test::doit (wfmo_reactor);
+
+ return 0;
+}
+#else /* !ACE_WIN32 */
+int
+ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ return 0;
+}
+#endif /* ACE_WIN32 */
diff --git a/ACE/examples/Reactor/WFMO_Reactor/Handle_Close.cpp b/ACE/examples/Reactor/WFMO_Reactor/Handle_Close.cpp
new file mode 100644
index 00000000000..9eb6d7c727a
--- /dev/null
+++ b/ACE/examples/Reactor/WFMO_Reactor/Handle_Close.cpp
@@ -0,0 +1,333 @@
+// $Id$
+//
+// ============================================================================
+//
+// = LIBRARY
+// examples
+//
+// = FILENAME
+// Handle_Close.cpp
+//
+// = DESCRIPTION
+//
+// This application tests whether handle_close gets called and if
+// the correct masks are passed along. The handler should get
+// handle_close called for all three masks (READ, WRITE, and
+// EXCEPT).
+//
+// = AUTHOR
+// Irfan Pyarali
+//
+// ============================================================================
+
+#include "ace/Get_Opt.h"
+#include "ace/Reactor.h"
+#include "ace/WFMO_Reactor.h"
+#include "ace/Select_Reactor.h"
+#include "ace/Auto_Ptr.h"
+#include "ace/Pipe.h"
+#include "ace/OS_main.h"
+
+ACE_RCSID(WFMO_Reactor, Handle_Close, "$Id: ")
+
+// Use the WFMO_Reactor
+static int opt_wfmo_reactor = 0;
+
+// Use the Select_Reactor
+static int opt_select_reactor = 0;
+
+// Make pipe readable in main()
+static int write_to_pipe_in_main = 0;
+
+// Cancel reads
+static int cancel_reads = 0;
+
+// Write some data to the pipe. This will cause handle_input to get
+// called.
+void
+write_to_pipe (ACE_Pipe &pipe)
+{
+ char *data = "hello";
+ size_t len = ACE_OS::strlen (data);
+
+ ssize_t result = ACE::send (pipe.write_handle (),
+ data,
+ len);
+ ACE_ASSERT ((size_t)result == len);
+ ACE_UNUSED_ARG (result);
+}
+
+// Simple handler class
+class Handler : public ACE_Event_Handler
+{
+public:
+ Handler (ACE_Pipe &pipe)
+ : pipe_ (pipe)
+ {
+ }
+
+ ~Handler (void)
+ {
+ this->reactor (0);
+ }
+
+ ACE_HANDLE get_handle (void) const
+ {
+ return this->pipe_.read_handle ();
+ }
+
+ int handle_close (ACE_HANDLE handle,
+ ACE_Reactor_Mask close_mask)
+ {
+ ACE_UNUSED_ARG (handle);
+ ACE_DEBUG ((LM_DEBUG,
+ "Handler::handle_close called with mask = %d\n",
+ close_mask));
+ return 0;
+ }
+
+ int handle_input (ACE_HANDLE handle)
+ {
+ ACE_UNUSED_ARG (handle);
+ ACE_DEBUG ((LM_DEBUG, "Handler::handle_input\n"));
+
+ // Remove for reading
+ return -1;
+ }
+
+ int handle_output (ACE_HANDLE handle)
+ {
+ ACE_UNUSED_ARG (handle);
+ ACE_DEBUG ((LM_DEBUG, "Handler::handle_output\n"));
+
+ // Optionally cancel reads
+ if (cancel_reads)
+ {
+ int result = this->reactor ()->cancel_wakeup (this,
+ ACE_Event_Handler::READ_MASK);
+ ACE_ASSERT (result != -1);
+ ACE_UNUSED_ARG (result);
+ }
+
+ // Write to the pipe; this causes handle_input to get called.
+ if (!write_to_pipe_in_main)
+ write_to_pipe (this->pipe_);
+
+ // Remove for writing
+ return -1;
+ }
+
+protected:
+ ACE_Pipe &pipe_;
+};
+
+class Different_Handler : public ACE_Event_Handler
+{
+public:
+
+ Different_Handler (ACE_Pipe &pipe)
+ : pipe_ (pipe)
+ {
+ }
+
+ ~Different_Handler (void)
+ {
+ this->reactor (0);
+ }
+
+ ACE_HANDLE get_handle (void) const
+ {
+ return this->pipe_.read_handle ();
+ }
+
+ int handle_close (ACE_HANDLE handle,
+ ACE_Reactor_Mask close_mask)
+ {
+ ACE_UNUSED_ARG (handle);
+ ACE_DEBUG ((LM_DEBUG,
+ "Different_Handler::handle_close called with mask = %d\n",
+ close_mask));
+ return 0;
+ }
+
+ int handle_input (ACE_HANDLE handle)
+ {
+ ACE_UNUSED_ARG (handle);
+ ACE_DEBUG ((LM_DEBUG, "Different_Handler::handle_input\n"));
+
+ // Remove for reading
+ int result = this->reactor ()->remove_handler (this,
+ ACE_Event_Handler::READ_MASK);
+ ACE_ASSERT (result == 0);
+ ACE_UNUSED_ARG (result);
+
+ return 0;
+ }
+
+ int handle_output (ACE_HANDLE handle)
+ {
+ ACE_UNUSED_ARG (handle);
+ ACE_DEBUG ((LM_DEBUG, "Different_Handler::handle_output\n"));
+
+ // Add for reading
+ int result = this->reactor ()->mask_ops (this,
+ ACE_Event_Handler::READ_MASK,
+ ACE_Reactor::ADD_MASK);
+ ACE_ASSERT (result != -1);
+
+ ACE_Reactor_Mask old_masks =
+ ACE_Event_Handler::WRITE_MASK |
+ ACE_Event_Handler::EXCEPT_MASK;
+
+ ACE_ASSERT (old_masks ==
+ static_cast<ACE_Reactor_Mask> (result));
+ ACE_UNUSED_ARG (old_masks);
+
+ // Get new masks
+ result = this->reactor ()->mask_ops (this,
+ ACE_Event_Handler::NULL_MASK,
+ ACE_Reactor::GET_MASK);
+ ACE_ASSERT (result != -1);
+
+ ACE_Reactor_Mask current_masks =
+ ACE_Event_Handler::READ_MASK |
+ ACE_Event_Handler::WRITE_MASK |
+ ACE_Event_Handler::EXCEPT_MASK;
+
+ ACE_ASSERT (current_masks ==
+ static_cast<ACE_Reactor_Mask> (result));
+ ACE_UNUSED_ARG (current_masks);
+
+ // Remove for writing
+ ACE_Reactor_Mask mask = ACE_Event_Handler::WRITE_MASK | ACE_Event_Handler::DONT_CALL;
+ result = this->reactor ()->remove_handler (this,
+ mask);
+ ACE_ASSERT (result == 0);
+
+ // Write to the pipe; this causes handle_input to get called.
+ if (!write_to_pipe_in_main)
+ write_to_pipe (this->pipe_);
+
+ return 0;
+ }
+
+protected:
+ ACE_Pipe &pipe_;
+};
+
+
+//
+// Selection of which reactor should get created
+//
+ACE_Reactor *
+create_reactor (void)
+{
+ ACE_Reactor_Impl *impl = 0;
+
+ if (opt_wfmo_reactor)
+ {
+#if defined (ACE_WIN32) && !defined (ACE_HAS_WINCE)
+ ACE_NEW_RETURN (impl,
+ ACE_WFMO_Reactor,
+ 0);
+#endif /* ACE_WIN32 */
+ }
+ else if (opt_select_reactor)
+ {
+ ACE_NEW_RETURN (impl,
+ ACE_Select_Reactor,
+ 0);
+ }
+ else
+ {
+ ACE_Reactor *singleton_reactor =
+ ACE_Reactor::instance ();
+ ACE_Reactor::instance (0);
+ return singleton_reactor;
+ }
+
+ ACE_Reactor *reactor = 0;
+ ACE_NEW_RETURN (reactor,
+ ACE_Reactor (impl,
+ 1),
+ 0);
+
+ return reactor;
+}
+
+int
+ACE_TMAIN (int argc, ACE_TCHAR *argv[])
+{
+ int result = 0;
+
+ // Parse args
+ ACE_Get_Opt getopt (argc, argv, ACE_TEXT ("swmc"), 1);
+ for (int c; (c = getopt ()) != -1; )
+ switch (c)
+ {
+ case 's':
+ opt_select_reactor = 1;
+ break;
+ case 'w':
+ opt_wfmo_reactor = 1;
+ break;
+ case 'm':
+ write_to_pipe_in_main = 1;
+ break;
+ case 'c':
+ cancel_reads = 1;
+ break;
+ }
+
+ // Create pipes
+ ACE_Pipe pipe1, pipe2;
+
+ result = pipe1.open ();
+ ACE_ASSERT (result == 0);
+
+ result = pipe2.open ();
+ ACE_ASSERT (result == 0);
+
+ // Create handlers
+ Handler handler (pipe1);
+ Different_Handler different_handler (pipe2);
+
+ // Manage memory automagically.
+ auto_ptr<ACE_Reactor> reactor (create_reactor ());
+
+ // Register handlers
+ ACE_Reactor_Mask handler_mask =
+ ACE_Event_Handler::READ_MASK |
+ ACE_Event_Handler::WRITE_MASK |
+ ACE_Event_Handler::EXCEPT_MASK;
+
+ ACE_Reactor_Mask different_handler_mask =
+ ACE_Event_Handler::WRITE_MASK |
+ ACE_Event_Handler::EXCEPT_MASK;
+
+ result = reactor->register_handler (&handler,
+ handler_mask);
+ ACE_ASSERT (result == 0);
+
+ result = reactor->register_handler (&different_handler,
+ different_handler_mask);
+ ACE_ASSERT (result == 0);
+
+ // Write to the pipe; this causes handle_input to get called.
+ if (write_to_pipe_in_main)
+ {
+ write_to_pipe (pipe1);
+ write_to_pipe (pipe2);
+ }
+
+ // Note that handle_output will get called automatically since the
+ // pipe is writable!
+
+ // Run for three seconds
+ ACE_Time_Value time (3);
+ reactor->run_reactor_event_loop (time);
+
+ ACE_DEBUG ((LM_DEBUG, "\nClosing down the application\n\n"));
+
+ return 0;
+}
diff --git a/ACE/examples/Reactor/WFMO_Reactor/Makefile.am b/ACE/examples/Reactor/WFMO_Reactor/Makefile.am
new file mode 100644
index 00000000000..cfa1c687b6c
--- /dev/null
+++ b/ACE/examples/Reactor/WFMO_Reactor/Makefile.am
@@ -0,0 +1,308 @@
+## Process this file with automake to create Makefile.in
+##
+## $Id$
+##
+## This file was generated by MPC. Any changes made directly to
+## this file will be lost the next time it is generated.
+##
+## MPC Command:
+## /acebuilds/ACE_wrappers-repository/bin/mwc.pl -include /acebuilds/MPC/config -include /acebuilds/MPC/templates -feature_file /acebuilds/ACE_wrappers-repository/local.features -noreldefs -type automake -exclude build,Kokyu
+
+ACE_BUILDDIR = $(top_builddir)
+ACE_ROOT = $(top_srcdir)
+
+noinst_PROGRAMS =
+
+## Makefile.WFMO_Reactor_APC.am
+
+if BUILD_WFMO
+if !BUILD_WINCE
+noinst_PROGRAMS += apc
+
+apc_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+apc_SOURCES = \
+ APC.cpp
+
+apc_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+endif !BUILD_WINCE
+endif BUILD_WFMO
+
+## Makefile.WFMO_Reactor_Abandoned.am
+
+if BUILD_WFMO
+noinst_PROGRAMS += abandoned
+
+abandoned_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+abandoned_SOURCES = \
+ Abandoned.cpp
+
+abandoned_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+endif BUILD_WFMO
+
+## Makefile.WFMO_Reactor_Console_Input.am
+
+if BUILD_WFMO
+noinst_PROGRAMS += console_input
+
+console_input_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+console_input_SOURCES = \
+ Console_Input.cpp
+
+console_input_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+endif BUILD_WFMO
+
+## Makefile.WFMO_Reactor_Directory_Changes.am
+
+if BUILD_WFMO
+noinst_PROGRAMS += directory_changes
+
+directory_changes_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+directory_changes_SOURCES = \
+ Directory_Changes.cpp
+
+directory_changes_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+endif BUILD_WFMO
+
+## Makefile.WFMO_Reactor_Exceptions.am
+
+if BUILD_WFMO
+noinst_PROGRAMS += exceptions
+
+exceptions_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+exceptions_SOURCES = \
+ Exceptions.cpp
+
+exceptions_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+endif BUILD_WFMO
+
+## Makefile.WFMO_Reactor_Handle_Close.am
+
+if BUILD_WFMO
+noinst_PROGRAMS += handle_close
+
+handle_close_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+handle_close_SOURCES = \
+ Handle_Close.cpp
+
+handle_close_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+endif BUILD_WFMO
+
+## Makefile.WFMO_Reactor_Multithreading.am
+
+if BUILD_WFMO
+noinst_PROGRAMS += multithreading
+
+multithreading_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+multithreading_SOURCES = \
+ Multithreading.cpp
+
+multithreading_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+endif BUILD_WFMO
+
+## Makefile.WFMO_Reactor_Network_Events.am
+
+if BUILD_WFMO
+noinst_PROGRAMS += network_events
+
+network_events_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+network_events_SOURCES = \
+ Network_Events.cpp
+
+network_events_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+endif BUILD_WFMO
+
+## Makefile.WFMO_Reactor_Prerun_State_Changes.am
+
+if BUILD_WFMO
+noinst_PROGRAMS += prerun_state_changes
+
+prerun_state_changes_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+prerun_state_changes_SOURCES = \
+ Prerun_State_Changes.cpp
+
+prerun_state_changes_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+endif BUILD_WFMO
+
+## Makefile.WFMO_Reactor_Registration.am
+
+if BUILD_WFMO
+noinst_PROGRAMS += registration
+
+registration_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+registration_SOURCES = \
+ Registration.cpp
+
+registration_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+endif BUILD_WFMO
+
+## Makefile.WFMO_Reactor_Registry_Changes.am
+
+if BUILD_WFMO
+if !BUILD_ACE_FOR_TAO
+if !BUILD_WINCE
+noinst_PROGRAMS += registry_changes
+
+registry_changes_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+registry_changes_SOURCES = \
+ Registry_Changes.cpp
+
+registry_changes_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+endif !BUILD_WINCE
+endif !BUILD_ACE_FOR_TAO
+endif BUILD_WFMO
+
+## Makefile.WFMO_Reactor_Removals.am
+
+if BUILD_WFMO
+noinst_PROGRAMS += removals
+
+removals_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+removals_SOURCES = \
+ Removals.cpp
+
+removals_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+endif BUILD_WFMO
+
+## Makefile.WFMO_Reactor_Suspended_Removals.am
+
+if BUILD_WFMO
+noinst_PROGRAMS += suspended_removals
+
+suspended_removals_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+suspended_removals_SOURCES = \
+ Suspended_Removals.cpp
+
+suspended_removals_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+endif BUILD_WFMO
+
+## Makefile.WFMO_Reactor_Talker.am
+
+if BUILD_WFMO
+if !BUILD_ACE_FOR_TAO
+if !BUILD_WINCE
+noinst_PROGRAMS += talker
+
+talker_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+talker_SOURCES = \
+ Talker.cpp
+
+talker_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+endif !BUILD_WINCE
+endif !BUILD_ACE_FOR_TAO
+endif BUILD_WFMO
+
+## Makefile.WFMO_Reactor_Timeouts.am
+
+if BUILD_WFMO
+noinst_PROGRAMS += timeouts
+
+timeouts_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+timeouts_SOURCES = \
+ Timeouts.cpp
+
+timeouts_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+endif BUILD_WFMO
+
+## Makefile.WFMO_Reactor_Window_Messages.am
+
+if BUILD_WFMO
+if !BUILD_ACE_FOR_TAO
+if !BUILD_WINCE
+noinst_PROGRAMS += window_messages
+
+window_messages_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+window_messages_SOURCES = \
+ Window_Messages.cpp
+
+window_messages_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+endif !BUILD_WINCE
+endif !BUILD_ACE_FOR_TAO
+endif BUILD_WFMO
+
+## Clean up template repositories, etc.
+clean-local:
+ -rm -f *~ *.bak *.rpo *.sym lib*.*_pure_* core core.*
+ -rm -f gcctemp.c gcctemp so_locations *.ics
+ -rm -rf cxx_repository ptrepository ti_files
+ -rm -rf templateregistry ir.out
+ -rm -rf ptrepository SunWS_cache Templates.DB
diff --git a/ACE/examples/Reactor/WFMO_Reactor/Multithreading.cpp b/ACE/examples/Reactor/WFMO_Reactor/Multithreading.cpp
new file mode 100644
index 00000000000..0778f375251
--- /dev/null
+++ b/ACE/examples/Reactor/WFMO_Reactor/Multithreading.cpp
@@ -0,0 +1,262 @@
+// $Id$
+//
+// ============================================================================
+//
+// = LIBRARY
+// examples
+//
+// = FILENAME
+// Multithreading.cpp
+//
+// = DESCRIPTION
+//
+// This application tests multiple threads simultaneously calling
+// Reactor::handle_events(). It also shows how different threads
+// can update the state of Reactor by registering and removing
+// Event_Handlers.
+//
+// Note that this test will only work with WFMO_Reactor
+//
+// = AUTHOR
+// Irfan Pyarali
+//
+// ============================================================================
+
+#include "ace/OS_main.h"
+
+#if defined (ACE_WIN32)
+
+#include "ace/Task.h"
+#include "ace/Reactor.h"
+#include "ace/WFMO_Reactor.h"
+#include "ace/Get_Opt.h"
+#include "ace/OS_NS_time.h"
+
+ACE_RCSID(WFMO_Reactor, Multithreading, "$Id$")
+
+static int concurrent_threads = 1;
+static int number_of_handles = static_cast<int> (ACE_Reactor::instance ()->size ());
+static int number_of_handles_to_signal = 1;
+static int interval = 2;
+static int iterations = 10;
+
+// Explain usage and exit.
+static void
+print_usage_and_die (void)
+{
+ ACE_DEBUG ((LM_DEBUG,
+ "usage: \n\t"
+ "[-t (# of threads - default 1)] \n\t"
+ "[-h (# of handlers) - default 62] \n\t"
+ "[-i (# time interval between signals) - default 2] \n\t"
+ "[-s (# of handles to signal) - default 1] \n\t"
+ "[-e (# of iterations) - default 10] \n\t"));
+ ACE_OS::exit (1);
+}
+
+// Parse the command-line arguments and set options.
+static void
+parse_args (int argc, ACE_TCHAR **argv)
+{
+ ACE_Get_Opt get_opt (argc, argv, ACE_TEXT("t:h:s:i:e:"));
+ int c;
+
+ while ((c = get_opt ()) != -1)
+ switch (c)
+ {
+ case 't':
+ concurrent_threads = ACE_OS::atoi (get_opt.opt_arg ());
+ break;
+ case 'e':
+ iterations = ACE_OS::atoi (get_opt.opt_arg ());
+ break;
+ case 'h':
+ number_of_handles = ACE_OS::atoi (get_opt.opt_arg ());
+ break;
+ case 'i':
+ interval = ACE_OS::atoi (get_opt.opt_arg ());
+ break;
+ case 's':
+ number_of_handles_to_signal = ACE_OS::atoi (get_opt.opt_arg ());
+ break;
+ default:
+ print_usage_and_die ();
+ break;
+ }
+}
+
+class Task_Handler : public ACE_Task<ACE_NULL_SYNCH>
+{
+public:
+ Task_Handler (size_t number_of_handles,
+ size_t concurrent_threads);
+ // Constructor.
+
+ ~Task_Handler (void);
+ // Destructor.
+
+ virtual int handle_close (ACE_HANDLE handle,
+ ACE_Reactor_Mask close_mask);
+ // Called when object is removed from the ACE_Reactor
+
+ int handle_signal (int signum, siginfo_t * = 0, ucontext_t * = 0);
+ // Handle events being signaled by the main thread.
+
+ virtual int handle_timeout (const ACE_Time_Value &tv,
+ const void *arg = 0);
+ // Called when timer expires.
+
+ int svc (void);
+ // Task event loop.
+
+ int signal (size_t index);
+ // Signal an event.
+
+private:
+ ACE_Auto_Event *events_;
+};
+
+// All threads do reactor->handle_events ()
+int
+Task_Handler::svc (void)
+{
+ // Try to become the owner
+ ACE_Reactor::instance ()->owner (ACE_Thread::self ());
+ // Run the event loop.
+ return ACE_Reactor::run_event_loop ();
+}
+
+Task_Handler::Task_Handler (size_t number_of_handles,
+ size_t concurrent_threads)
+{
+ ACE_NEW (this->events_, ACE_Auto_Event [number_of_handles]);
+
+ for (size_t i = 0; i < number_of_handles; ++i)
+ if (ACE_Reactor::instance ()->register_handler (this,
+ this->events_[i].handle ()) == -1)
+ ACE_ERROR ((LM_ERROR,
+ "%p\t cannot register handle %d with Reactor\n",
+ "Task_Handler::Task_Handler",
+ i));
+
+ // Make us an active object.
+ if (this->activate (THR_NEW_LWP,
+ static_cast<int> (concurrent_threads)) == -1)
+ ACE_ERROR ((LM_ERROR, "%p\t cannot activate task\n",
+ "activate"));
+}
+
+Task_Handler::~Task_Handler (void)
+{
+ this->reactor (0);
+ delete [] this->events_;
+}
+
+
+int
+Task_Handler::handle_signal (int, siginfo_t *siginfo, ucontext_t *)
+{
+ // When signaled, print message, remove self, and add self
+ // This will force Reactor to update its internal handle tables
+
+ ACE_DEBUG ((LM_DEBUG,
+ "(%t) calls handle_signal for handle %d\n",
+ siginfo->si_handle_));
+
+ if (ACE_Reactor::instance ()->remove_handler (siginfo->si_handle_,
+ ACE_Event_Handler::DONT_CALL) == -1)
+ return -1;
+ // ACE_ERROR_RETURN ((LM_ERROR,
+ // "(%t) %p\tTask cannot be unregistered from Reactor: handle value = %d\n",
+ // "Task_Handler::handle_signal",
+ // siginfo->si_handle_), -1);
+
+ if (ACE_Reactor::instance ()->register_handler (this,
+ siginfo->si_handle_) == -1)
+ return -1;
+ // ACE_ERROR_RETURN ((LM_ERROR,
+ // "(%t) %p\tTask cannot be registered with Reactor: handle value = %d\n",
+ // "Task_Handler::handle_signal",
+ // siginfo->si_handle_), -1);
+ return 0;
+}
+
+int
+Task_Handler::handle_close (ACE_HANDLE handle,
+ ACE_Reactor_Mask)
+{
+ ACE_DEBUG ((LM_DEBUG, "(%t) handle_close() called: handle value = %d\n",
+ handle));
+ return 0;
+}
+
+int
+Task_Handler::handle_timeout (const ACE_Time_Value &,
+ const void *arg)
+{
+ ACE_DEBUG ((LM_DEBUG, "(%t) handle_timeout() called: iteration value = %d\n",
+ size_t (arg)));
+ return 0;
+}
+
+int
+Task_Handler::signal (size_t index)
+{
+ return this->events_[index].signal ();
+}
+
+int
+ACE_TMAIN (int argc, ACE_TCHAR **argv)
+{
+ parse_args (argc, argv);
+ Task_Handler task (number_of_handles,
+ concurrent_threads);
+
+ ACE_OS::srand (ACE_OS::time (0L));
+
+ for (int i = 1; i <= iterations; i++)
+ {
+ // Sleep for a while
+ ACE_OS::sleep (interval);
+
+ // Randomly generate events
+ ACE_DEBUG ((LM_DEBUG, "********************************************************\n"));
+ ACE_DEBUG ((LM_DEBUG, "(%t -- main thread) signaling %d events : iteration = %d\n",
+ number_of_handles_to_signal,
+ i));
+ ACE_DEBUG ((LM_DEBUG, "********************************************************\n"));
+
+ // Setup a timer for the task
+ if (ACE_Reactor::instance ()->schedule_timer (&task,
+ (void *)((size_t)i),
+ ACE_Time_Value::zero) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "schedule_timer"), -1);
+
+ for (int i = 0; i < number_of_handles_to_signal; i++)
+ // Randomly select a handle to signal.
+ task.signal (ACE_OS::rand() % number_of_handles);
+ }
+
+ // Sleep for a while
+ ACE_OS::sleep (interval);
+
+ // End the Reactor event loop
+ ACE_Reactor::end_event_loop ();
+
+ // Wait for all threads to exit
+ ACE_Thread_Manager::instance ()->wait ();
+
+ // Close the Reactor singleton before exiting this function.
+ // If we wait for the Object Manager to do this, it will be too
+ // late since Task_Handler instance would have disappeared.
+ ACE_Reactor::close_singleton ();
+
+ return 0;
+}
+#else /* !ACE_WIN32 */
+int
+ACE_TMAIN (int, ACE_TCHAR **)
+{
+ return 0;
+}
+#endif /* ACE_WIN32 */
diff --git a/ACE/examples/Reactor/WFMO_Reactor/Network_Events.cpp b/ACE/examples/Reactor/WFMO_Reactor/Network_Events.cpp
new file mode 100644
index 00000000000..9935679a60f
--- /dev/null
+++ b/ACE/examples/Reactor/WFMO_Reactor/Network_Events.cpp
@@ -0,0 +1,211 @@
+// $Id$
+//
+// ============================================================================
+//
+// = LIBRARY
+// examples
+//
+// = FILENAME
+// Network_Events.cpp
+//
+// = DESCRIPTION
+//
+// This application tests Reactor to make sure that it responds
+// correctly to different kinds of network events.
+//
+// The test starts off by creating a Network_Listener, that listens
+// for connections at ACE_DEFAULT_SERVER_PORT. When a client
+// connects, a Network_Handler is created. Network_Handler reads
+// messages off the socket and prints them out. This is done until
+// the remote side shuts down. Multiple clients can connect at the
+// same time.
+//
+// Events tested in this example includes ACCEPT, READ, and CLOSE masks.
+//
+// To run this example, start an instance of this example and
+// connect to it using telnet (to port
+// ACE_DEFAULT_SERVER_PORT(20002)).
+//
+// = AUTHOR
+// Irfan Pyarali
+//
+// ============================================================================
+
+#include "ace/Reactor.h"
+#include "ace/WFMO_Reactor.h"
+#include "ace/INET_Addr.h"
+#include "ace/SOCK_Stream.h"
+#include "ace/SOCK_Acceptor.h"
+#include "ace/OS_main.h"
+
+ACE_RCSID(WFMO_Reactor, Network_Events, "$Id$")
+
+class Network_Handler : public ACE_Event_Handler
+{
+public:
+ Network_Handler (ACE_SOCK_Stream &s);
+ // Default constructor
+
+ virtual int handle_input (ACE_HANDLE handle);
+ virtual int handle_close (ACE_HANDLE handle,
+ ACE_Reactor_Mask close_mask);
+ virtual ACE_HANDLE get_handle (void) const;
+
+ ACE_SOCK_Stream stream_;
+
+};
+
+Network_Handler::Network_Handler (ACE_SOCK_Stream &s)
+ : stream_ (s)
+{
+ this->reactor (ACE_Reactor::instance ());
+
+ int result = this->reactor ()->register_handler (this, READ_MASK);
+ ACE_ASSERT (result == 0);
+ ACE_UNUSED_ARG (result);
+}
+
+ACE_HANDLE
+Network_Handler::get_handle (void) const
+{
+ return this->stream_.get_handle ();
+}
+
+int
+Network_Handler::handle_input (ACE_HANDLE handle)
+{
+ ACE_DEBUG ((LM_DEBUG, "Network_Handler::handle_input handle = %d\n", handle));
+
+ while (1)
+ {
+ char message[BUFSIZ];
+ int result = this->stream_.recv (message, sizeof message);
+ if (result > 0)
+ {
+ message[result] = 0;
+ ACE_DEBUG ((LM_DEBUG, "Remote message: %s\n", message));
+ }
+ else if (result == 0)
+ {
+ ACE_DEBUG ((LM_DEBUG, "Connection closed\n"));
+ return -1;
+ }
+ else if (errno == EWOULDBLOCK)
+ {
+ return 0;
+ }
+ else
+ {
+ ACE_DEBUG ((LM_DEBUG, "Problems in receiving data, result = %d", result));
+ return -1;
+ }
+ }
+}
+
+int
+Network_Handler::handle_close (ACE_HANDLE handle,
+ ACE_Reactor_Mask)
+{
+ ACE_DEBUG ((LM_DEBUG, "Network_Handler::handle_close handle = %d\n", handle));
+
+ this->stream_.close ();
+ delete this;
+
+ ACE_Reactor::end_event_loop ();
+
+ return 0;
+}
+
+class Network_Listener : public ACE_Event_Handler
+{
+public:
+ Network_Listener (void);
+ // Default constructor
+ ~Network_Listener (void);
+ // Default constructor
+
+ virtual int handle_input (ACE_HANDLE handle);
+ virtual int handle_close (ACE_HANDLE handle,
+ ACE_Reactor_Mask close_mask);
+ ACE_HANDLE get_handle (void) const;
+
+ ACE_INET_Addr local_address_;
+ ACE_SOCK_Acceptor acceptor_;
+};
+
+Network_Listener::Network_Listener (void)
+ : local_address_ (ACE_DEFAULT_SERVER_PORT),
+ acceptor_ (local_address_, 1)
+{
+ this->reactor (ACE_Reactor::instance ());
+ int result = this->reactor ()->register_handler (this,
+ ACE_Event_Handler::ACCEPT_MASK);
+ ACE_ASSERT (result == 0);
+ ACE_UNUSED_ARG (result);
+}
+
+Network_Listener::~Network_Listener (void)
+{
+}
+
+ACE_HANDLE
+Network_Listener::get_handle (void) const
+{
+ return this->acceptor_.get_handle ();
+}
+
+int
+Network_Listener::handle_input (ACE_HANDLE handle)
+{
+ ACE_DEBUG ((LM_DEBUG, "Network_Listener::handle_input handle = %d\n", handle));
+
+ ACE_INET_Addr remote_address;
+ ACE_SOCK_Stream stream;
+
+ // Try to find out if the implementation of the reactor that we are
+ // using requires us to reset the event association for the newly
+ // created handle. This is because the newly created handle will
+ // inherit the properties of the listen handle, including its event
+ // associations.
+ int reset_new_handle = this->reactor ()->uses_event_associations ();
+
+ int result = this->acceptor_.accept (stream, // stream
+ &remote_address, // remote address
+ 0, // timeout
+ 1, // restart
+ reset_new_handle); // reset new handler
+ ACE_ASSERT (result == 0);
+ ACE_UNUSED_ARG (result);
+
+ ACE_DEBUG ((LM_DEBUG, "Remote connection from: "));
+ remote_address.dump ();
+
+ Network_Handler *handler;
+ ACE_NEW_RETURN (handler, Network_Handler (stream), -1);
+
+ return 0;
+}
+
+int
+Network_Listener::handle_close (ACE_HANDLE handle,
+ ACE_Reactor_Mask)
+{
+ ACE_DEBUG ((LM_DEBUG, "Network_Listener::handle_close handle = %d\n", handle));
+
+ this->acceptor_.close ();
+
+ delete this;
+
+ return 0;
+}
+
+int
+ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ Network_Listener *listener = 0;
+ listener = new Network_Listener;
+
+ ACE_Reactor::run_event_loop ();
+
+ return 0;
+};
diff --git a/ACE/examples/Reactor/WFMO_Reactor/Prerun_State_Changes.cpp b/ACE/examples/Reactor/WFMO_Reactor/Prerun_State_Changes.cpp
new file mode 100644
index 00000000000..e276fd7d3f8
--- /dev/null
+++ b/ACE/examples/Reactor/WFMO_Reactor/Prerun_State_Changes.cpp
@@ -0,0 +1,66 @@
+// $Id$
+//
+// ============================================================================
+//
+// = LIBRARY
+// examples
+//
+// = FILENAME
+// Prerun_State_Changes.cpp
+//
+// = DESCRIPTION
+//
+// Tests the Reactor's ability to handle state changes before
+// getting a chance to run.
+//
+// = AUTHOR
+//
+// Irfan Pyarali
+//
+// ============================================================================
+
+#include "ace/Reactor.h"
+#include "ace/OS_main.h"
+
+ACE_RCSID(WFMO_Reactor, Prerun_State_Changes, "$Id$")
+
+class Event_Handler : public ACE_Event_Handler
+// = TITLE
+// Generic Event Handler.
+//
+{
+public:
+ virtual int handle_close (ACE_HANDLE handle, ACE_Reactor_Mask mask)
+ {
+ ACE_UNUSED_ARG(mask);
+ ACE_DEBUG ((LM_DEBUG,
+ "event handler %d closed.\n",
+ (size_t) handle));
+ delete this;
+ return 0;
+ }
+};
+
+int
+ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ ACE_HANDLE handle = (ACE_HANDLE) ::socket (PF_INET, SOCK_STREAM, 0);
+
+ Event_Handler *event_handler = new Event_Handler;
+
+ int result = ACE_Reactor::instance ()->register_handler (handle,
+ event_handler,
+ ACE_Event_Handler::READ_MASK);
+ ACE_ASSERT (result == 0);
+
+ result = ACE_Reactor::instance ()->register_handler (handle,
+ event_handler,
+ ACE_Event_Handler::WRITE_MASK | ACE_Event_Handler::QOS_MASK);
+ ACE_ASSERT (result == 0);
+
+ result = ACE_Reactor::instance ()->remove_handler (handle,
+ ACE_Event_Handler::READ_MASK | ACE_Event_Handler::DONT_CALL);
+ ACE_ASSERT (result == 0);
+
+ return 0;
+}
diff --git a/ACE/examples/Reactor/WFMO_Reactor/Registration.cpp b/ACE/examples/Reactor/WFMO_Reactor/Registration.cpp
new file mode 100644
index 00000000000..a9429bdd433
--- /dev/null
+++ b/ACE/examples/Reactor/WFMO_Reactor/Registration.cpp
@@ -0,0 +1,169 @@
+// $Id$
+//
+// ============================================================================
+//
+// = LIBRARY
+// examples
+//
+// = FILENAME
+// Registration.cpp
+//
+// = DESCRIPTION
+//
+// This test application tests a wide range of registration,
+// suspension, resumption, and removal of events from Reactor.
+//
+// The application initially registers two events with Reactor. A
+// auxiliary thread is created to do the signaling on the
+// events. When the first event is signaled, the event is suspended
+// from Reactor. The event is then signaled again, but is "lost"
+// since the handler has been suspended. When the second event is
+// signal, the first event is resumed and the second is
+// suspended. When the first event is signaled again, both events
+// are removed from Reactor.
+//
+// This test shows off the following features of Reactor:
+// - Registration
+// - Suspension
+// - Resumption
+// - Removal (while active and while suspended)
+//
+// = AUTHOR
+// Irfan Pyarali
+//
+// ============================================================================
+
+#include "ace/OS_main.h"
+
+#if defined (ACE_WIN32)
+
+#include "ace/Reactor.h"
+#include "ace/Auto_Event.h"
+#include "ace/OS_NS_unistd.h"
+
+ACE_RCSID(WFMO_Reactor, Registration, "$Id$")
+
+// Globals for this test
+int stop_test = 0;
+ACE_Reactor reactor;
+
+
+class Simple_Handler : public ACE_Event_Handler
+{
+public:
+ Simple_Handler (void);
+ // Default constructor
+
+ virtual int handle_signal (int signum, siginfo_t * = 0, ucontext_t * = 0);
+ virtual int handle_close (ACE_HANDLE handle,
+ ACE_Reactor_Mask close_mask);
+
+ ACE_Auto_Event event1_;
+ ACE_Auto_Event event2_;
+ int handle_signal_count_;
+ int handle_close_count_;
+};
+
+Simple_Handler::Simple_Handler (void)
+ : handle_signal_count_ (0),
+ handle_close_count_ (0)
+{
+}
+
+int
+Simple_Handler::handle_signal (int, siginfo_t *s, ucontext_t *)
+{
+ ACE_HANDLE handle = s->si_handle_;
+ ACE_UNUSED_ARG (handle);
+
+ this->handle_signal_count_++;
+
+ if (this->handle_signal_count_ == 1)
+ this->reactor ()->suspend_handler (event1_.handle ());
+ else if (this->handle_signal_count_ == 2)
+ {
+ this->reactor ()->resume_handler (event1_.handle ());
+ this->reactor ()->suspend_handler (event2_.handle ());
+ }
+ else if (this->handle_signal_count_ == 3)
+ {
+ this->reactor ()->remove_handler (event1_.handle (),
+ ACE_Event_Handler::NULL_MASK);
+ this->reactor ()->remove_handler (event2_.handle (),
+ ACE_Event_Handler::NULL_MASK);
+ }
+ return 0;
+}
+
+int
+Simple_Handler::handle_close (ACE_HANDLE handle,
+ ACE_Reactor_Mask)
+{
+ ACE_DEBUG ((LM_DEBUG, "Simple_Handler::handle_close handle = %d\n", handle));
+ this->handle_close_count_++;
+
+ if (this->handle_close_count_ == 1)
+ stop_test = 0;
+ else if (this->handle_close_count_ == 2)
+ stop_test = 1;
+
+ return 0;
+}
+
+// Globals for this test
+Simple_Handler simple_handler;
+
+void
+worker (void)
+{
+ ACE_DEBUG ((LM_DEBUG, "(%t) Thread creation\n"));
+ ACE_DEBUG ((LM_DEBUG, "(%t) Thread sleeping\n"));
+ ACE_OS::sleep (1);
+ ACE_DEBUG ((LM_DEBUG, "(%t) Thread signaling %d\n", simple_handler.event1_.handle()));
+ simple_handler.event1_.signal ();
+ ACE_DEBUG ((LM_DEBUG, "(%t) Thread sleeping\n"));
+ ACE_OS::sleep (1);
+ ACE_DEBUG ((LM_DEBUG, "(%t) Thread signaling %d\n", simple_handler.event1_.handle()));
+ ACE_DEBUG ((LM_DEBUG, "Note: This signal should be \"lost\" because of the suspended handler\n"));
+ simple_handler.event1_.signal ();
+ ACE_DEBUG ((LM_DEBUG, "(%t) Thread sleeping\n"));
+ ACE_OS::sleep (1);
+ ACE_DEBUG ((LM_DEBUG, "(%t) Thread resetting %d\n", simple_handler.event1_.handle()));
+ simple_handler.event1_.reset ();
+ ACE_DEBUG ((LM_DEBUG, "(%t) Thread signaling %d\n", simple_handler.event2_.handle()));
+ simple_handler.event2_.signal ();
+ ACE_DEBUG ((LM_DEBUG, "(%t) Thread sleeping\n"));
+ ACE_OS::sleep (1);
+ ACE_DEBUG ((LM_DEBUG, "(%t) Thread signaling %d\n", simple_handler.event1_.handle()));
+ simple_handler.event1_.signal ();
+ ACE_DEBUG ((LM_DEBUG, "(%t) Thread death\n"));
+}
+
+int
+ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ int result = reactor.register_handler (&simple_handler,
+ simple_handler.event1_.handle ());
+ ACE_ASSERT (result == 0);
+
+ result = reactor.register_handler (&simple_handler,
+ simple_handler.event2_.handle ());
+ ACE_ASSERT (result == 0);
+
+ result = ACE_OS::thr_create ((ACE_THR_FUNC) worker, 0, 0, 0);
+ ACE_ASSERT (result == 0);
+
+ result = 0;
+ while (!stop_test && result != -1)
+ {
+ result = reactor.handle_events ();
+ }
+ return 0;
+};
+#else /* !ACE_WIN32 */
+int
+ACE_TMAIN (int, ACE_TCHAR **)
+{
+ return 0;
+}
+#endif /* ACE_WIN32 */
diff --git a/ACE/examples/Reactor/WFMO_Reactor/Registry_Changes.cpp b/ACE/examples/Reactor/WFMO_Reactor/Registry_Changes.cpp
new file mode 100644
index 00000000000..be787293e65
--- /dev/null
+++ b/ACE/examples/Reactor/WFMO_Reactor/Registry_Changes.cpp
@@ -0,0 +1,146 @@
+// $Id$
+//
+// ============================================================================
+//
+// = LIBRARY
+// examples
+//
+// = FILENAME
+// Registry_Changes.cpp
+//
+// = DESCRIPTION
+//
+// This application tests the working of Reactor when users are
+// interested in monitoring changes in the registry.
+//
+// = AUTHOR
+// Irfan Pyarali
+//
+// ============================================================================
+
+#include "ace/OS_main.h"
+
+#if defined (ACE_WIN32)
+
+#include "ace/Reactor.h"
+#include "ace/Registry.h"
+#include "ace/Auto_Event.h"
+#include "ace/OS_NS_unistd.h"
+
+ACE_RCSID(WFMO_Reactor, Registry_Changes, "$Id$")
+
+static int stop_test = 0;
+static HKEY context_to_monitor = HKEY_CURRENT_USER;
+static const ACE_TCHAR *temp_context_name = ACE_TEXT ("ACE temporary context");
+
+class Event_Handler : public ACE_Event_Handler
+{
+public:
+ Event_Handler (ACE_Reactor &reactor);
+ ~Event_Handler (void);
+ int handle_signal (int signum, siginfo_t * = 0, ucontext_t * = 0);
+ int handle_close (ACE_HANDLE handle,
+ ACE_Reactor_Mask close_mask);
+ ACE_Registry::Naming_Context &context (void);
+
+private:
+ ACE_Auto_Event event_;
+ ACE_Registry::Naming_Context context_;
+};
+
+Event_Handler::Event_Handler (ACE_Reactor &reactor)
+ : context_ (context_to_monitor)
+{
+ this->reactor (&reactor);
+
+ if (::RegNotifyChangeKeyValue (this->context_.key (), // handle of key to watch
+ FALSE, // flag for subkey notification
+ REG_NOTIFY_CHANGE_NAME, // changes to be reported
+ this->event_.handle (), // handle of signaled event
+ TRUE // flag for asynchronous reporting
+ ) != ERROR_SUCCESS)
+ ACE_ERROR ((LM_ERROR, "RegNotifyChangeKeyValue could not be setup\n"));
+
+ if (this->reactor ()->register_handler (this,
+ this->event_.handle ()) != 0)
+ ACE_ERROR ((LM_ERROR, "Registration with Reactor could not be done\n"));
+}
+
+Event_Handler::~Event_Handler (void)
+{
+}
+
+int
+Event_Handler::handle_signal (int, siginfo_t *, ucontext_t *)
+{
+ if (stop_test)
+ this->reactor ()->close ();
+ else if (::RegNotifyChangeKeyValue (this->context_.key (), // handle of key to watch
+ FALSE, // flag for subkey notification
+ REG_NOTIFY_CHANGE_NAME, // changes to be reported
+ this->event_.handle (), // handle of signaled event
+ TRUE // flag for asynchronous reporting
+ ) != ERROR_SUCCESS)
+ ACE_ERROR ((LM_ERROR,
+ "RegNotifyChangeKeyValue could not be setup\n"));
+ return 0;
+}
+
+int
+Event_Handler::handle_close (ACE_HANDLE,
+ ACE_Reactor_Mask)
+{
+ ACE_DEBUG ((LM_DEBUG, "Event_Handler removed from Reactor\n"));
+ return 0;
+}
+
+ACE_Registry::Naming_Context &
+Event_Handler::context (void)
+{
+ return this->context_;
+}
+
+void
+worker (Event_Handler *event_handler)
+{
+ ACE_DEBUG ((LM_DEBUG, "(%t) Thread creation\n"));
+ ACE_DEBUG ((LM_DEBUG, "(%t) Thread creating temporary registry entry\n"));
+
+ ACE_Registry::Naming_Context temp_context;
+ int result = event_handler->context ().bind_new_context (temp_context_name,
+ temp_context);
+
+ if (result == -1)
+ ACE_ERROR ((LM_ERROR, "Error in creating %s: %p\n", temp_context_name, "bind_new_context"));
+ else
+ {
+ ACE_DEBUG ((LM_DEBUG, "(%t) Thread sleeping\n"));
+ ACE_OS::sleep (3);
+
+ ACE_DEBUG ((LM_DEBUG, "(%t) Thread removing registry entry\n"));
+ stop_test = 1;
+ event_handler->context ().unbind_context (temp_context_name);
+ }
+}
+
+int
+ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ ACE_Reactor reactor;
+ Event_Handler handler (reactor);
+
+ int result = ACE_OS::thr_create ((ACE_THR_FUNC) worker, &handler, 0, 0);
+ ACE_ASSERT (result == 0);
+
+ for (result = 0; result != -1; result = reactor.handle_events ())
+ continue;
+
+ return 0;
+}
+#else /* !ACE_WIN32 */
+int
+ACE_TMAIN (int, ACE_TCHAR **)
+{
+ return 0;
+}
+#endif /* ACE_WIN32 */
diff --git a/ACE/examples/Reactor/WFMO_Reactor/Removals.cpp b/ACE/examples/Reactor/WFMO_Reactor/Removals.cpp
new file mode 100644
index 00000000000..260b9e897ee
--- /dev/null
+++ b/ACE/examples/Reactor/WFMO_Reactor/Removals.cpp
@@ -0,0 +1,114 @@
+// $Id$
+//
+// ============================================================================
+//
+// = LIBRARY
+// examples
+//
+// = FILENAME
+// Removals.cpp
+//
+// = DESCRIPTION
+//
+// Tests the Reactor's ability to handle simultaneous events. If
+// you pass anything on the command-line, then each handler
+// requests to be removed from the Reactor after each event.
+//
+// = AUTHOR
+// Tim Harrison
+// Irfan Pyarali
+//
+// ============================================================================
+
+#include "ace/OS_main.h"
+
+#if defined (ACE_WIN32)
+
+#include "ace/Reactor.h"
+#include "ace/Service_Config.h"
+#include "ace/Event.h"
+
+ACE_RCSID(WFMO_Reactor, Removals, "$Id$")
+
+class Event_Handler : public ACE_Event_Handler
+// = TITLE
+// Generic Event Handler.
+//
+// = DESCRIPTION
+//
+// Creates event. Registers with Reactor. Signals event. If
+// created with -close_down- it returns -1 from handle signal.
+{
+public:
+ Event_Handler (int event_number,
+ int close_down)
+ : event_number_ (event_number),
+ close_down_ (close_down)
+ {
+ if (ACE_Reactor::instance ()->register_handler (this,
+ this->event_.handle ()) == -1)
+ ACE_ERROR ((LM_ERROR, "%p\tevent handler %d cannot be added to Reactor\n", "", event_number_));
+ this->event_.signal ();
+ }
+
+ virtual int handle_signal (int, siginfo_t *, ucontext_t *)
+ {
+ if (this->close_down_)
+ return -1;
+ else
+ return 0;
+ }
+
+ virtual int handle_close (ACE_HANDLE, ACE_Reactor_Mask)
+ {
+ ACE_DEBUG ((LM_DEBUG, "event handler %d closed.\n", event_number_));
+ delete this;
+ return 0;
+ }
+
+ virtual ACE_HANDLE get_handle (void) const
+ {
+ return event_.handle ();
+ }
+
+private:
+ int event_number_;
+ // Our event number.
+
+ int close_down_;
+ // Shall we close down or not.
+
+ ACE_Event event_;
+ // Signaled to shut down the handler.
+};
+
+int
+ACE_TMAIN (int argc, ACE_TCHAR *[])
+{
+ int close_down = argc > 1 ? 1 : 0;
+
+ for (size_t i = 1; i <= ACE_Reactor::instance ()->size (); i++)
+ new Event_Handler (static_cast<int> (i), close_down);
+
+ int result = 0;
+ ACE_Time_Value time (1);
+ while (1)
+ {
+ result = ACE_Reactor::instance ()->handle_events (time);
+ if (result == 0 && errno == ETIME)
+ {
+ ACE_DEBUG ((LM_DEBUG, "No more work left: timing out\n"));
+ break;
+ }
+ if (result == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, "%p.\n", "main"), -1);
+ }
+ return 0;
+}
+#else /* !ACE_WIN32 */
+int
+ACE_TMAIN (int , ACE_TCHAR *[])
+{
+ return 0;
+}
+#endif /* ACE_WIN32 */
diff --git a/ACE/examples/Reactor/WFMO_Reactor/Suspended_Removals.cpp b/ACE/examples/Reactor/WFMO_Reactor/Suspended_Removals.cpp
new file mode 100644
index 00000000000..ead467146a5
--- /dev/null
+++ b/ACE/examples/Reactor/WFMO_Reactor/Suspended_Removals.cpp
@@ -0,0 +1,173 @@
+// $Id$
+//
+// ============================================================================
+//
+// = LIBRARY
+// examples
+//
+// = FILENAME
+// Suspended_Removals.cpp
+//
+// = DESCRIPTION
+//
+// Tests the Reactor's ability to handle removal of suspended
+// handles.
+//
+// = AUTHOR
+// Irfan Pyarali
+//
+// ============================================================================
+
+#include "ace/OS_main.h"
+
+#if defined (ACE_WIN32)
+
+#include "ace/Reactor.h"
+#include "ace/WFMO_Reactor.h"
+
+ACE_RCSID(WFMO_Reactor, Suspended_Removals, "$Id$")
+
+class Event_Handler : public ACE_Event_Handler
+{
+public:
+
+ ACE_HANDLE get_handle (void) const
+ {
+ return this->event_.handle ();
+ }
+
+ ACE_Event event_;
+};
+
+class ACE_WFMO_Reactor_Test
+{
+public:
+ static void check_for_valid_state (ACE_WFMO_Reactor &wfmo_reactor,
+ size_t handles_to_be_added,
+ size_t handles_to_be_suspended,
+ size_t handles_to_be_resumed,
+ size_t handles_to_be_deleted)
+ {
+ ACE_ASSERT (wfmo_reactor.handler_rep_.handles_to_be_added_ == handles_to_be_added);
+ ACE_ASSERT (wfmo_reactor.handler_rep_.handles_to_be_suspended_ == handles_to_be_suspended);
+ ACE_ASSERT (wfmo_reactor.handler_rep_.handles_to_be_resumed_ == handles_to_be_resumed);
+ ACE_ASSERT (wfmo_reactor.handler_rep_.handles_to_be_deleted_ == handles_to_be_deleted);
+ }
+};
+
+int
+ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ Event_Handler handler;
+ ACE_WFMO_Reactor reactor;
+ ACE_Reactor base_reactor (&reactor);
+ ACE_Time_Value time (1);
+
+ int result =
+ reactor.register_handler (&handler);
+ ACE_ASSERT (result == 0);
+
+ ACE_WFMO_Reactor_Test::check_for_valid_state (reactor,
+ 1, 0, 0, 0);
+
+ result =
+ reactor.remove_handler (&handler,
+ ACE_Event_Handler::DONT_CALL |
+ ACE_Event_Handler::ALL_EVENTS_MASK);
+ ACE_ASSERT (result == 0);
+
+ ACE_WFMO_Reactor_Test::check_for_valid_state (reactor,
+ 1, 0, 0, 1);
+
+ result = base_reactor.run_reactor_event_loop (time);
+ ACE_ASSERT (result != -1);
+
+ ACE_WFMO_Reactor_Test::check_for_valid_state (reactor,
+ 0, 0, 0, 0);
+
+ result =
+ reactor.register_handler (&handler);
+ ACE_ASSERT (result == 0);
+
+ ACE_WFMO_Reactor_Test::check_for_valid_state (reactor,
+ 1, 0, 0, 0);
+
+ result = base_reactor.run_reactor_event_loop (time);
+ ACE_ASSERT (result != -1);
+
+ ACE_WFMO_Reactor_Test::check_for_valid_state (reactor,
+ 0, 0, 0, 0);
+
+ result =
+ reactor.suspend_handler (&handler);
+ ACE_ASSERT (result == 0);
+
+ ACE_WFMO_Reactor_Test::check_for_valid_state (reactor,
+ 0, 1, 0, 0);
+
+ result =
+ reactor.remove_handler (&handler,
+ ACE_Event_Handler::DONT_CALL |
+ ACE_Event_Handler::ALL_EVENTS_MASK);
+ ACE_ASSERT (result == 0);
+
+ ACE_WFMO_Reactor_Test::check_for_valid_state (reactor,
+ 0, 0, 0, 1);
+
+ result = base_reactor.run_reactor_event_loop (time);
+ ACE_ASSERT (result != -1);
+
+ ACE_WFMO_Reactor_Test::check_for_valid_state (reactor,
+ 0, 0, 0, 0);
+
+ result =
+ reactor.register_handler (&handler);
+ ACE_ASSERT (result == 0);
+
+ ACE_WFMO_Reactor_Test::check_for_valid_state (reactor,
+ 1, 0, 0, 0);
+
+ result =
+ reactor.suspend_handler (&handler);
+ ACE_ASSERT (result == 0);
+
+ ACE_WFMO_Reactor_Test::check_for_valid_state (reactor,
+ 1, 1, 0, 0);
+
+ result = base_reactor.run_reactor_event_loop (time);
+ ACE_ASSERT (result != -1);
+
+ ACE_WFMO_Reactor_Test::check_for_valid_state (reactor,
+ 0, 0, 0, 0);
+
+ result =
+ reactor.resume_handler (&handler);
+ ACE_ASSERT (result == 0);
+
+ ACE_WFMO_Reactor_Test::check_for_valid_state (reactor,
+ 0, 0, 1, 0);
+
+ result =
+ reactor.remove_handler (&handler,
+ ACE_Event_Handler::DONT_CALL |
+ ACE_Event_Handler::ALL_EVENTS_MASK);
+ ACE_ASSERT (result == 0);
+
+ ACE_WFMO_Reactor_Test::check_for_valid_state (reactor,
+ 0, 0, 0, 1);
+
+ result = base_reactor.run_reactor_event_loop (time);
+ ACE_ASSERT (result != -1);
+
+ ACE_WFMO_Reactor_Test::check_for_valid_state (reactor,
+ 0, 0, 0, 0);
+
+ return 0;
+}
+#else /* !ACE_WIN32 */
+int
+ACE_TMAIN (int , ACE_TCHAR *[])
+{
+ return 0;
+}
+#endif /* ACE_WIN32 */
diff --git a/ACE/examples/Reactor/WFMO_Reactor/Talker.cpp b/ACE/examples/Reactor/WFMO_Reactor/Talker.cpp
new file mode 100644
index 00000000000..32438088614
--- /dev/null
+++ b/ACE/examples/Reactor/WFMO_Reactor/Talker.cpp
@@ -0,0 +1,594 @@
+// $Id$
+
+// ============================================================================
+//
+// = LIBRARY
+// examples
+//
+// = FILENAME
+// Talker.cpp
+//
+// = DESCRIPTION
+//
+// This test application tests a wide range of events that can be
+// demultiplexed using various ACE utilities. Events used include
+// ^C events, reading from STDIN, vanilla Win32 events, thread
+// exits, Reactor notifications, proactive reads, and proactive
+// writes.
+//
+// The proactive I/O events are demultiplexed by the ACE_Proactor.
+// The thread exits, notications, and vanilla Win32 events are
+// demultiplexed by the ACE_Reactor. To enable a single thread
+// to run all these events, the Proactor is integrated with the
+// Reactor.
+//
+// The test application prototypes a simple talk program. Two
+// instances of the application connect. Input from either console
+// is displayed on the others console also. Because of the evils
+// of Win32 STDIN, a separate thread is used to read from STDIN.
+// To test the Proactor and Reactor, I/O between the remote
+// processes is performed proactively and interactions between the
+// STDIN thread and the main thread are performed reactively.
+//
+// The following description of the test application is in two
+// parts. The participants section explains the main components
+// involved in the application. The collaboration section
+// describes how the partipants interact in response to the
+// multiple event types which occur.
+//
+// The Reactor test application has the following participants:
+//
+// . Reactor -- The Reactor demultiplexes Win32 "waitable"
+// events using WaitForMultipleObjects.
+//
+// . Proactor -- The proactor initiates and demultiplexes
+// overlapped I/O operations. The Proactor registers with the
+// Reactor so that a single-thread can demultiplex all
+// application events.
+//
+// . STDIN_Handler -- STDIN_Handler is an Active Object which reads
+// from STDIN and forwards the input to the Peer_Handler. This
+// runs in a separate thread to make the test more interesting.
+// However, STDIN is "waitable", so in general it can be waited on
+// by the ACE Reactor, thanks MicroSlush!
+//
+// . Peer_Handler -- The Peer_Handler connects to another instance
+// of test_reactor. It Proactively reads and writes data to the
+// peer. When the STDIN_Handler gives it messages, it fowards them
+// to the remote peer. When it receives messages from the remote
+// peer, it prints the output to the console.
+//
+// The collaborations of the participants are as follows:
+//
+// . Initialization
+//
+// Peer_Handler -- connects to the remote peer. It then begins
+// proactively reading from the remote connection. Note that it
+// will be notified by the Proactor when a read completes. It
+// also registers a notification strategy with message queue so
+// that it is notified when the STDIN_Handler posts a message
+// onto the queue.
+//
+// STDIN_Handler -- STDIN_Handler registers a signal handler for
+// SIGINT. This just captures the exception so that the kernel
+// doesn't kill our process; We want to exit gracefully. It also
+// creates an Exit_Hook object which registers the
+// STDIN_Handler's thread handle with the Reactor. The
+// Exit_Hook will get called back when the STDIN_Handler thread
+// exits. After registering these, it blocks reading from STDIN.
+//
+// Proactor -- is registered with the Reactor.
+//
+// The main thread of control waits in the Reactor.
+//
+// . STDIN events -- When the STDIN_Handler thread reads from
+// STDIN, it puts the message on Peer_Handler's message queue. It
+// then returns to reading from STDIN.
+//
+// . Message enqueue -- The Reactor thread wakes up and calls
+// Peer_Handler::handle_output. The Peer_Handler then tries to
+// dequeue a message from its message queue. If it can, the
+// message is Proactively sent to the remote peer. Note that the
+// Peer_Handler will be notified with this operation is complete.
+// The Peer_Handler then falls back into the Reactor event loop.
+//
+// . Send complete event -- When a proactive send is complete, the
+// Proactor is notified by the Reactor. The Proactor, in turn,
+// notifies the Peer_Handler. The Peer_Handler then checks for
+// more messages from the message queue. If there are any, it
+// tries to send them. If there are not, it returns to the
+// Reactor event loop.
+//
+// . Read complete event -- When a proactive read is complete (the
+// Peer_Handler initiated a proactive read when it connected to the
+// remote peer), the Proactor is notified by the Reactor. The
+// Proactor, in turn notifies the Peer_Handler. If the read was
+// successful the Peer_Handler just displays the received msg to
+// the console and reinvokes a proactive read from the network
+// connection. If the read failed (i.e. the remote peer exited),
+// the Peer_Handler sets a flag to end the event loop and returns.
+// This will cause the application to exit.
+//
+// . ^C events -- When the user types ^C at the console, the
+// STDIN_Handler's signal handler will be called. It does nothing,
+// but as a result of the signal, the STDIN_Handler thread will
+// exit.
+//
+// . STDIN_Handler thread exits -- The Exit_Hook will get called
+// back from the Reactor. Exit_Hook::handle_signal sets a flag
+// to end the event loop and returns. This will cause the
+// application to exit.
+//
+//
+// To run example, start an instance of the test with an optional
+// local port argument (as the acceptor). Start the other instance
+// with -h <hostname> and -p <server port>. Type in either the
+// client or server windows and your message should show up in the
+// other window. Control C to exit.
+//
+// = AUTHOR
+// Tim Harrison
+// Irfan Pyarali
+//
+// ============================================================================
+
+#include "ace/OS_main.h"
+
+#if defined (ACE_WIN32)
+
+#include "ace/Reactor.h"
+#include "ace/Reactor_Notification_Strategy.h"
+#include "ace/WIN32_Proactor.h"
+#include "ace/Proactor.h"
+#include "ace/SOCK_Connector.h"
+#include "ace/SOCK_Acceptor.h"
+#include "ace/Get_Opt.h"
+#include "ace/Service_Config.h"
+#include "ace/Task.h"
+#include "ace/OS_NS_unistd.h"
+
+ACE_RCSID(WFMO_Reactor, Talker, "$Id$")
+
+typedef ACE_Task<ACE_MT_SYNCH> MT_TASK;
+
+class Peer_Handler : public MT_TASK, public ACE_Handler
+// = TITLE
+// Connect to a server. Receive messages from STDIN_Handler
+// and forward them to the server using proactive I/O.
+{
+public:
+ // = Initialization methods.
+ Peer_Handler (int argc, ACE_TCHAR *argv[]);
+ ~Peer_Handler (void);
+
+ int open (void * =0);
+ // This method creates the network connection to the remote peer.
+ // It does blocking connects and accepts depending on whether a
+ // hostname was specified from the command line.
+
+ virtual void handle_read_stream (const ACE_Asynch_Read_Stream::Result &result);
+ // This method will be called when an asynchronous read completes on a stream.
+ // The remote peer has sent us something. If it succeeded, print
+ // out the message and reinitiate a read. Otherwise, fail. In both
+ // cases, delete the message sent.
+
+ virtual void handle_write_stream (const ACE_Asynch_Write_Stream::Result &result);
+ // This method will be called when an asynchronous write completes on a strea_m.
+ // One of our asynchronous writes to the remote peer has completed.
+ // Make sure it succeeded and then delete the message.
+
+ virtual ACE_HANDLE handle (void) const;
+ // Get the I/O handle used by this <handler>. This method will be
+ // called by the ACE_Asynch_* classes when an ACE_INVALID_HANDLE is
+ // passed to <open>.
+
+ void handle (ACE_HANDLE);
+ // Set the ACE_HANDLE value for this Handler.
+
+ virtual int handle_close (ACE_HANDLE, ACE_Reactor_Mask);
+ // We've been removed from the Reactor.
+
+ virtual int handle_output (ACE_HANDLE fd);
+ // Called when output events should start. Note that this is
+ // automatically invoked by the
+ // <ACE_Reactor_Notificiation_Strategy>.
+
+private:
+ ACE_SOCK_Stream stream_;
+ // Socket that we have connected to the server.
+
+ ACE_Reactor_Notification_Strategy strategy_;
+ // The strategy object that the reactor uses to notify us when
+ // something is added to the queue.
+
+ // = Remote peer info.
+ ACE_TCHAR *host_;
+ // Name of remote host.
+
+ u_short port_;
+ // Port number for remote host.
+
+ ACE_Asynch_Read_Stream rd_stream_;
+ // Read stream
+
+ ACE_Asynch_Write_Stream wr_stream_;
+ // Write stream
+
+ ACE_Message_Block mb_;
+ // Message Block for reading from the network
+};
+
+class STDIN_Handler : public ACE_Task<ACE_NULL_SYNCH>
+// = TITLE
+// Active Object. Reads from STDIN and passes message blocks to
+// the peer handler.
+{
+public:
+ STDIN_Handler (MT_TASK &ph);
+ // Initialization.
+
+ virtual int open (void * = 0);
+ // Activate object.
+
+ virtual int close (u_long = 0);
+ // Shut down.
+
+ int svc (void);
+ // Thread runs here as an active object.
+
+ int handle_close (ACE_HANDLE,
+ ACE_Reactor_Mask);
+
+private:
+ static void handler (int signum);
+ // Handle a ^C. (Do nothing, this just illustrates how we can catch
+ // signals along with the other things).
+
+ void register_thread_exit_hook (void);
+ // Helper function to register with the Reactor for thread exit.
+
+ virtual int handle_signal (int index, siginfo_t *, ucontext_t *);
+ // The STDIN thread has exited. This means the user hit ^C. We can
+ // end the event loop.
+
+ MT_TASK &ph_;
+ // Send all input to ph_.
+
+ ACE_HANDLE thr_handle_;
+ // Handle of our thread.
+};
+
+Peer_Handler::Peer_Handler (int argc, ACE_TCHAR *argv[])
+ : strategy_ (ACE_Reactor::instance (),
+ this,
+ ACE_Event_Handler::WRITE_MASK),
+ host_ (0),
+ port_ (ACE_DEFAULT_SERVER_PORT),
+ mb_ (BUFSIZ)
+{
+ // This code sets up the message to notify us when a new message is
+ // added to the queue. Actually, the queue notifies Reactor which
+ // then notifies us.
+ this->msg_queue ()->notification_strategy (&this->strategy_);
+
+ ACE_Get_Opt get_opt (argc, argv, ACE_TEXT("h:p:"));
+ int c;
+
+ while ((c = get_opt ()) != EOF)
+ {
+ switch (c)
+ {
+ case 'h':
+ host_ = get_opt.opt_arg ();
+ break;
+ case 'p':
+ port_ = ACE_OS::atoi (get_opt.opt_arg ());
+ break;
+ }
+ }
+}
+
+Peer_Handler::~Peer_Handler (void)
+{
+}
+
+// This method creates the network connection to the remote peer. It
+// does blocking connects and accepts depending on whether a hostname
+// was specified from the command line.
+
+int
+Peer_Handler::open (void *)
+{
+ if (host_ != 0) // Connector
+ {
+ ACE_INET_Addr addr (port_, host_);
+ ACE_SOCK_Connector connector;
+
+ // Establish connection with server.
+ if (connector.connect (stream_, addr) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "connect"), -1);
+
+ ACE_DEBUG ((LM_DEBUG, "(%t) connected.\n"));
+ }
+ else // Acceptor
+ {
+ ACE_SOCK_Acceptor acceptor;
+ ACE_INET_Addr local_addr (port_);
+
+ if ((acceptor.open (local_addr) == -1) ||
+ (acceptor.accept (this->stream_) == -1))
+ ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "accept failed"), -1);
+
+ ACE_DEBUG ((LM_DEBUG, "(%t) accepted.\n"));
+ }
+
+ int result = this->rd_stream_.open (*this);
+ if (result != 0)
+ return result;
+
+ result = this->wr_stream_.open (*this);
+ if (result != 0)
+ return result;
+
+ result = this->rd_stream_.read (this->mb_,
+ this->mb_.size ());
+ return result;
+}
+
+// One of our asynchronous writes to the remote peer has completed.
+// Make sure it succeeded and then delete the message.
+
+void
+Peer_Handler::handle_write_stream (const ACE_Asynch_Write_Stream::Result &result)
+{
+ if (result.bytes_transferred () <= 0)
+ ACE_DEBUG ((LM_DEBUG, "(%t) %p bytes = %d\n", "Message failed",
+ result.bytes_transferred ()));
+
+ // This was allocated by the STDIN_Handler, queued, dequeued, passed
+ // to the proactor, and now passed back to us.
+ result.message_block ().release ();
+}
+
+// The remote peer has sent us something. If it succeeded, print
+// out the message and reinitiate a read. Otherwise, fail. In both
+// cases, delete the message sent.
+
+
+void
+Peer_Handler::handle_read_stream (const ACE_Asynch_Read_Stream::Result &result)
+{
+ if (result.bytes_transferred () > 0 &&
+ this->mb_.length () > 0)
+ {
+ this->mb_.rd_ptr ()[result.bytes_transferred ()] = '\0';
+ // Print out the message received from the server.
+ ACE_DEBUG ((LM_DEBUG, "%s", this->mb_.rd_ptr ()));
+ }
+ else
+ {
+ // If a read failed, we will assume it's because the remote peer
+ // went away. We will end the event loop. Since we're in the
+ // main thread, we don't need to do a notify.
+ ACE_Reactor::end_event_loop();
+ return;
+ }
+
+ // Reset pointers
+ this->mb_.wr_ptr (this->mb_.wr_ptr () - result.bytes_transferred ());
+
+ // Start off another read
+ if (this->rd_stream_.read (this->mb_,
+ this->mb_.size ()) == -1)
+ ACE_ERROR ((LM_ERROR, "%p Read initiate.\n", "Peer_Handler"));
+}
+
+// This is so the Proactor can get our handle.
+ACE_HANDLE
+Peer_Handler::handle (void) const
+{
+ return this->stream_.get_handle ();
+}
+
+void
+Peer_Handler::handle (ACE_HANDLE handle)
+{
+ this->stream_.set_handle (handle);
+}
+
+// We've been removed from the Reactor.
+int
+Peer_Handler::handle_close (ACE_HANDLE, ACE_Reactor_Mask)
+{
+ ACE_DEBUG ((LM_DEBUG, "(%t) Peer_Handler closing down\n"));
+ return 0;
+}
+
+// New stuff added to the message queue. Try to dequeue a message.
+int
+Peer_Handler::handle_output (ACE_HANDLE)
+{
+ ACE_Message_Block *mb;
+
+ ACE_Time_Value tv (ACE_Time_Value::zero);
+
+ // Forward the message to the remote peer receiver.
+ if (this->getq (mb, &tv) != -1)
+ {
+ if (this->wr_stream_.write (*mb,
+ mb->length ()) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, "%p Write initiate.\n", "Peer_Handler"), -1);
+ }
+ return 0;
+}
+
+void
+STDIN_Handler::handler (int signum)
+{
+ ACE_DEBUG ((LM_DEBUG, "(%t) signal = %S\n", signum));
+}
+
+STDIN_Handler::STDIN_Handler (MT_TASK &ph)
+ : ph_ (ph)
+{
+ // Register for ^C from the console. We just need to catch the
+ // exception so that the kernel doesn't kill our process.
+ // Registering this signal handler just tells the kernel that we
+ // know what we're doing; to leave us alone.
+
+ ACE_OS::signal (SIGINT, (ACE_SignalHandler) STDIN_Handler::handler);
+};
+
+// Activate object.
+
+int
+STDIN_Handler::open (void *)
+{
+ if (this->activate (THR_NEW_LWP | THR_DETACHED) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "spawn"), -1);
+
+ return 0;
+}
+
+// Shut down.
+
+int
+STDIN_Handler::close (u_long)
+{
+ ACE_DEBUG ((LM_DEBUG, "(%t) thread is exiting.\n"));
+ return 0;
+}
+
+// Thread runs here.
+
+int
+STDIN_Handler::svc (void)
+{
+ this->register_thread_exit_hook ();
+
+ for (;;)
+ {
+ ACE_Message_Block *mb = new ACE_Message_Block (BUFSIZ);
+
+ // Read from stdin into mb.
+ int read_result = ACE_OS::read (ACE_STDIN,
+ mb->rd_ptr (),
+ mb->size ());
+
+ // If read succeeds, put mb to peer handler, else end the loop.
+ if (read_result > 0)
+ {
+ mb->wr_ptr (read_result);
+ // Note that this call will first enqueue mb onto the peer
+ // handler's message queue, which will then turn around and
+ // notify the Reactor via the Notification_Strategy. This
+ // will subsequently signal the Peer_Handler, which will
+ // react by calling back to its handle_output() method,
+ // which dequeues the message and sends it to the peer
+ // across the network.
+ this->ph_.putq (mb);
+ }
+ else
+ {
+ mb->release ();
+ break;
+ }
+ }
+
+ // handle_signal will get called on the main proactor thread since
+ // we just exited and the main thread is waiting on our thread exit.
+ return 0;
+}
+
+// Register an exit hook with the reactor.
+
+void
+STDIN_Handler::register_thread_exit_hook (void)
+{
+ // Get a real handle to our thread.
+ ACE_Thread_Manager::instance ()->thr_self (this->thr_handle_);
+
+ // Register ourselves to get called back when our thread exits.
+
+ if (ACE_Reactor::instance ()->
+ register_handler (this, this->thr_handle_) == -1)
+ ACE_ERROR ((LM_ERROR, "Exit_Hook Register failed.\n"));
+}
+
+// The STDIN thread has exited. This means the user hit ^C. We can
+// end the event loop and delete ourself.
+
+int
+STDIN_Handler::handle_signal (int, siginfo_t *si, ucontext_t *)
+{
+ if (si != 0)
+ {
+ ACE_ASSERT (this->thr_handle_ == si->si_handle_);
+ ACE_Reactor::end_event_loop ();
+ }
+ return 0;
+}
+
+int
+STDIN_Handler::handle_close (ACE_HANDLE,
+ ACE_Reactor_Mask)
+{
+ delete this;
+ return 0;
+}
+
+int
+ACE_TMAIN (int argc, ACE_TCHAR *argv[])
+{
+ // Let the proactor know that it will be used with Reactor
+ // Create specific proactor
+ ACE_WIN32_Proactor win32_proactor (0, 1);
+ // Get the interface proactor
+ ACE_Proactor proactor (&win32_proactor);
+ // Put it as the instance.
+ ACE_Proactor::instance (&proactor);
+
+ // Open handler for remote peer communications this will run from
+ // the main thread.
+ Peer_Handler peer_handler (argc, argv);
+
+ if (peer_handler.open () == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%p open failed, errno = %d.\n",
+ "peer_handler", errno), 0);
+
+ // Open active object for reading from stdin.
+ STDIN_Handler *stdin_handler =
+ new STDIN_Handler (peer_handler);
+
+ // Spawn thread.
+ if (stdin_handler->open () == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%p open failed, errno = %d.\n",
+ "stdin_handler", errno), 0);
+
+ // Register proactor with Reactor so that we can demultiplex
+ // "waitable" events and I/O operations from a single thread.
+ if (ACE_Reactor::instance ()->register_handler
+ (ACE_Proactor::instance ()->implementation ()) != 0)
+ ACE_ERROR_RETURN ((LM_ERROR, "%p failed to register Proactor.\n",
+ argv[0]), -1);
+
+ // Run main event demultiplexor.
+ ACE_Reactor::run_event_loop ();
+
+ // Remove proactor with Reactor.
+ if (ACE_Reactor::instance ()->remove_handler
+ (ACE_Proactor::instance ()->implementation (), ACE_Event_Handler::DONT_CALL) != 0)
+ ACE_ERROR_RETURN ((LM_ERROR, "%p failed to register Proactor.\n",
+ argv[0]), -1);
+
+ return 0;
+}
+#else /* !ACE_WIN32 */
+int
+ACE_TMAIN (int , ACE_TCHAR *[])
+{
+ return 0;
+}
+#endif /* ACE_WIN32 */
diff --git a/ACE/examples/Reactor/WFMO_Reactor/Timeouts.cpp b/ACE/examples/Reactor/WFMO_Reactor/Timeouts.cpp
new file mode 100644
index 00000000000..8cc37a940bc
--- /dev/null
+++ b/ACE/examples/Reactor/WFMO_Reactor/Timeouts.cpp
@@ -0,0 +1,83 @@
+// $Id$
+//
+// ============================================================================
+//
+// = LIBRARY
+// examples
+//
+// = FILENAME
+// Timeouts.cpp
+//
+// = DESCRIPTION
+//
+// This example application shows how to write Reactor event
+// loops that handle events for some fixed amount of time.
+//
+// Run this example (without arguments) to see the timers
+// expire. The order should be:
+//
+// foo, bar, foo, bar, foo, foo, bar, foo, bar, foo
+//
+// = AUTHOR
+// Tim Harrison
+// Irfan Pyarali
+//
+// ============================================================================
+
+#include "ace/Reactor.h"
+#include "ace/Service_Config.h"
+#include "ace/OS_main.h"
+
+ACE_RCSID(WFMO_Reactor, Timeouts, "$Id$")
+
+class Timeout_Handler : public ACE_Event_Handler
+// = TITLE
+// Generic timeout handler.
+{
+public:
+ Timeout_Handler (void)
+ : count_ (0) {}
+
+ virtual int handle_timeout (const ACE_Time_Value &tv,
+ const void *arg)
+ // Print out when timeouts occur.
+ {
+ ACE_UNUSED_ARG(tv);
+ ACE_DEBUG ((LM_DEBUG,
+ "%d timeout occurred for %s.\n",
+ ++count_,
+ (char *) arg));
+ return 0;
+ }
+
+private:
+ int count_;
+};
+
+int
+ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ Timeout_Handler handler;
+
+ // Register a 3 second timer.
+ ACE_Time_Value bar_tv (3);
+ ACE_Reactor::instance ()->schedule_timer (&handler,
+ (void *) "Bar",
+ bar_tv,
+ bar_tv);
+
+ // Register a 2 second timer.
+ ACE_Time_Value foo_tv (2);
+ ACE_Reactor::instance ()->schedule_timer (&handler,
+ (void *) "Foo",
+ foo_tv,
+ foo_tv);
+ // Handle events for 12 seconds.
+ ACE_Time_Value run_time (12);
+ if (ACE_Reactor::run_event_loop(run_time) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, "%p.\n", "main"), -1);
+
+ ACE_Reactor::instance ()->cancel_timer(&handler);
+
+ return 0;
+}
diff --git a/ACE/examples/Reactor/WFMO_Reactor/WFMO_Reactor.mpc b/ACE/examples/Reactor/WFMO_Reactor/WFMO_Reactor.mpc
new file mode 100644
index 00000000000..eec632ee696
--- /dev/null
+++ b/ACE/examples/Reactor/WFMO_Reactor/WFMO_Reactor.mpc
@@ -0,0 +1,118 @@
+// -*- MPC -*-
+// $Id$
+
+project(*Abandoned): aceexe, wfmo {
+ exename = abandoned
+ Source_Files {
+ Abandoned.cpp
+ }
+}
+
+project(*APC): aceexe, wfmo {
+ avoids += wince
+ exename = apc
+ Source_Files {
+ APC.cpp
+ }
+}
+
+project(*Console_Input): aceexe, wfmo {
+ exename = console_input
+ Source_Files {
+ Console_Input.cpp
+ }
+}
+
+project(*Directory_Changes): aceexe, wfmo {
+ exename = directory_changes
+ Source_Files {
+ Directory_Changes.cpp
+ }
+}
+
+project(*Exceptions): aceexe, wfmo {
+ exename = exceptions
+ Source_Files {
+ Exceptions.cpp
+ }
+}
+
+project(*Handle_Close): aceexe, wfmo {
+ exename = handle_close
+ Source_Files {
+ Handle_Close.cpp
+ }
+}
+
+project(*Multithreading): aceexe, wfmo {
+ exename = multithreading
+ Source_Files {
+ Multithreading.cpp
+ }
+}
+
+project(*Network_Events): aceexe, wfmo {
+ exename = network_events
+ Source_Files {
+ Network_Events.cpp
+ }
+}
+
+project(*Prerun_State_Changes): aceexe, wfmo {
+ exename = prerun_state_changes
+ Source_Files {
+ Prerun_State_Changes.cpp
+ }
+}
+
+project(*Registration): aceexe, wfmo {
+ exename = registration
+ Source_Files {
+ Registration.cpp
+ }
+}
+
+project(*Registry_Changes): aceexe, wfmo {
+ avoids += ace_for_tao wince
+ exename = registry_changes
+ Source_Files {
+ Registry_Changes.cpp
+ }
+}
+
+project(*Removals): aceexe, wfmo {
+ exename = removals
+ Source_Files {
+ Removals.cpp
+ }
+}
+
+project(*Suspended_Removals): aceexe, wfmo {
+ exename = suspended_removals
+ Source_Files {
+ Suspended_Removals.cpp
+ }
+}
+
+project(*Talker): aceexe, wfmo {
+ avoids += ace_for_tao wince
+ exename = talker
+ Source_Files {
+ Talker.cpp
+ }
+}
+
+project(*Timeouts): aceexe, wfmo {
+ exename = timeouts
+ Source_Files {
+ Timeouts.cpp
+ }
+}
+
+project(*Window_Messages): aceexe, wfmo {
+ avoids += ace_for_tao wince
+ exename = window_messages
+ Source_Files {
+ Window_Messages.cpp
+ }
+}
diff --git a/ACE/examples/Reactor/WFMO_Reactor/Window_Messages.cpp b/ACE/examples/Reactor/WFMO_Reactor/Window_Messages.cpp
new file mode 100644
index 00000000000..f5a1994168c
--- /dev/null
+++ b/ACE/examples/Reactor/WFMO_Reactor/Window_Messages.cpp
@@ -0,0 +1,100 @@
+// $Id$
+
+// ============================================================================
+//
+// = LIBRARY
+// examples
+//
+// = FILENAME
+// Window_Messages.cpp
+//
+// = DESCRIPTION
+//
+// Tests the Msg_WFMO_Reactor's ability to handle regular events
+// and window messages.
+//
+// = AUTHOR
+//
+// Irfan Pyarali <irfan@cs.wustl.edu>
+//
+// ============================================================================
+
+#include "ace/OS_main.h"
+
+#if defined (ACE_WIN32)
+
+#include "ace/Msg_WFMO_Reactor.h"
+#include "ace/Reactor.h"
+#include "ace/Auto_Ptr.h"
+#include "ace/Auto_Event.h"
+
+ACE_RCSID(WFMO_Reactor, Window_Messages, "$Id$")
+
+class Event_Handler : public ACE_Event_Handler
+{
+public:
+ int handle_signal (int signum, siginfo_t * = 0, ucontext_t * = 0);
+
+ ACE_Auto_Event handle_;
+ int iterations_;
+};
+
+int
+Event_Handler::handle_signal (int, siginfo_t *, ucontext_t *)
+{
+ --this->iterations_;
+
+ if (this->iterations_ == 0)
+ ACE_Reactor::end_event_loop ();
+
+ return 0;
+}
+
+static Event_Handler *global_event_handler;
+
+void WINAPI
+timer_callback (HWND,
+ UINT,
+ UINT,
+ DWORD dwTime)
+{
+ ACE_DEBUG ((LM_DEBUG, "(%t) timeout occured @ %u\n", dwTime));
+
+ global_event_handler->handle_.signal ();
+}
+
+int
+ACE_TMAIN (int, ACE_TCHAR*[])
+{
+ // Manage memory automagically.
+ ACE_Reactor_Impl *impl = new ACE_Msg_WFMO_Reactor;
+ auto_ptr<ACE_Reactor> reactor (new ACE_Reactor (impl, 1));
+ ACE_Reactor::instance (reactor.get ());
+
+ Event_Handler event_handler;
+ global_event_handler = &event_handler;
+
+ event_handler.iterations_ = 5;
+ int result = ACE_Reactor::instance ()->register_handler (&event_handler,
+ event_handler.handle_.handle ());
+ ACE_ASSERT (result == 0);
+
+ ACE_Time_Value timeout (1);
+ result = ::SetTimer (NULL, // handle of window for timer messages
+ 0, // timer identifier
+ timeout.msec (), // time-out value
+ (TIMERPROC) &timer_callback // address of timer procedure
+ );
+ ACE_ASSERT (result != 0);
+
+ ACE_Reactor::run_event_loop ();
+
+ return 0;
+}
+#else /* !ACE_WIN32 */
+int
+ACE_TMAIN (int , ACE_TCHAR *[])
+{
+ return 0;
+}
+#endif /* ACE_WIN32 */
diff --git a/ACE/examples/Reactor/WFMO_Reactor/run_test.pl b/ACE/examples/Reactor/WFMO_Reactor/run_test.pl
new file mode 100755
index 00000000000..cc445c64043
--- /dev/null
+++ b/ACE/examples/Reactor/WFMO_Reactor/run_test.pl
@@ -0,0 +1,68 @@
+eval '(exit $?0)' && eval 'exec perl -S $0 ${1+"$@"}'
+ & eval 'exec perl -S $0 $argv:q'
+ if 0;
+
+# $Id$
+# -*- perl -*-
+
+use lib '../../../bin';
+use PerlACE::Run_Test;
+
+#
+# These tests only run on Win32
+#
+if ($^O ne "MSWin32")
+{
+ exit;
+}
+
+$test_timeout = 60;
+
+@tests =
+ (
+ "Abandoned",
+ "APC",
+# "Console_Input", # This test is interactive
+ "Directory_Changes",
+ "Exceptions",
+ "Handle_Close",
+ "Multithreading",
+# "Network_Events", # This test is interactive
+ "Prerun_State_Changes",
+ "Registration",
+ "Registry_Changes",
+ "Removals",
+ "Suspended_Removals",
+# "Talker", # This test is interactive
+ "Timeouts",
+ "Window_Messages",
+ );
+
+for $test (@tests)
+{
+ print STDOUT "\n________________________________________\n";
+ print STDOUT "\nStarting test \"$test\"";
+ print STDOUT "\n________________________________________\n\n";
+
+ $test_process = new PerlACE::Process ($test);
+
+ if (! -x $test_process->Executable ()) {
+ print STDERR "Error: " . $test_process->Executable () .
+ " does not exist or is not runnable\n";
+ }
+ else
+ {
+ $test_process->Spawn ();
+ $test_result = $test_process->WaitKill ($test_timeout);
+
+ if ($test_result != 0)
+ {
+ print STDERR "\n________________________________________\n";
+ print STDERR "\nERROR: \"$test\" returned $test_result";
+ print STDERR "\n________________________________________\n";
+ }
+ }
+ print STDOUT "\n________________________________________\n";
+ print STDOUT "\n\"$test\" completed";
+ print STDOUT "\n________________________________________\n";
+}
diff --git a/ACE/examples/Registry/Makefile.am b/ACE/examples/Registry/Makefile.am
new file mode 100644
index 00000000000..1e02e33abb2
--- /dev/null
+++ b/ACE/examples/Registry/Makefile.am
@@ -0,0 +1,60 @@
+## Process this file with automake to create Makefile.in
+##
+## $Id$
+##
+## This file was generated by MPC. Any changes made directly to
+## this file will be lost the next time it is generated.
+##
+## MPC Command:
+## /acebuilds/ACE_wrappers-repository/bin/mwc.pl -include /acebuilds/MPC/config -include /acebuilds/MPC/templates -feature_file /acebuilds/ACE_wrappers-repository/local.features -noreldefs -type automake -exclude build,Kokyu
+
+ACE_BUILDDIR = $(top_builddir)
+ACE_ROOT = $(top_srcdir)
+
+noinst_PROGRAMS =
+
+## Makefile.Registry_Iterator.am
+
+if BUILD_WINREGISTRY
+if !BUILD_ACE_FOR_TAO
+noinst_PROGRAMS += iterator
+
+iterator_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+iterator_SOURCES = \
+ test_registry_iterator.cpp
+
+iterator_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+endif !BUILD_ACE_FOR_TAO
+endif BUILD_WINREGISTRY
+
+## Makefile.Registry_Update.am
+
+if BUILD_WINREGISTRY
+if !BUILD_ACE_FOR_TAO
+noinst_PROGRAMS += update
+
+update_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+update_SOURCES = \
+ test_registry_update.cpp
+
+update_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+endif !BUILD_ACE_FOR_TAO
+endif BUILD_WINREGISTRY
+
+## Clean up template repositories, etc.
+clean-local:
+ -rm -f *~ *.bak *.rpo *.sym lib*.*_pure_* core core.*
+ -rm -f gcctemp.c gcctemp so_locations *.ics
+ -rm -rf cxx_repository ptrepository ti_files
+ -rm -rf templateregistry ir.out
+ -rm -rf ptrepository SunWS_cache Templates.DB
diff --git a/ACE/examples/Registry/Registry.mpc b/ACE/examples/Registry/Registry.mpc
new file mode 100644
index 00000000000..e2e048f02c0
--- /dev/null
+++ b/ACE/examples/Registry/Registry.mpc
@@ -0,0 +1,17 @@
+// -*- MPC -*-
+// $Id$
+
+project(*iterator) : aceexe, winregistry {
+ exename = iterator
+
+ Source_Files {
+ test_registry_iterator.cpp
+ }
+}
+project(*update) : aceexe, winregistry {
+ exename = update
+
+ Source_Files {
+ test_registry_update.cpp
+ }
+}
diff --git a/ACE/examples/Registry/test_registry_iterator.cpp b/ACE/examples/Registry/test_registry_iterator.cpp
new file mode 100644
index 00000000000..e24a418ca07
--- /dev/null
+++ b/ACE/examples/Registry/test_registry_iterator.cpp
@@ -0,0 +1,146 @@
+// $Id$
+
+// This example uses the ACE_Registry class to iterator through the
+// entries in the predefined registries. The host of iteration can be
+// varied through argv[1]. If no host is specified the local host is
+// used. This is very similar to how regedt32 starts up.
+//
+// This examples points the cool iterators in ACE_Registry
+
+#include "ace/OS_main.h"
+
+#if defined (ACE_WIN32)
+
+#include "ace/Registry.h"
+
+// FUZZ: disable check_for_streams_include
+#include "ace/streams.h"
+
+ACE_RCSID(Registry, test_registry_iterator, "$Id$")
+
+// Indentation while printing names
+static const u_long INDENTATION_LEVEL = 3;
+
+// Prototypes
+static int print_naming_context (ACE_Registry::Naming_Context &naming_context,
+ u_long indentation);
+static void print_object (const ACE_TString &name,
+ u_long indentation);
+static void print_context (ACE_Registry::Naming_Context &parent,
+ const ACE_TString &name,
+ u_long indentation);
+static void indent (u_long indentation);
+
+int
+ACE_TMAIN (int argc, ACE_TCHAR *argv[])
+{
+ int result;
+ ACE_Registry::Naming_Context naming_context;
+
+ // Connect to a predefined naming context
+ result = ACE_Predefined_Naming_Contexts::connect (naming_context,
+ HKEY_LOCAL_MACHINE,
+ // HKEY_CLASSES_ROOT,
+ // HKEY_USERS,
+ // HKEY_CURRENT_USER,
+ argc == 2 ? argv[1] : 0);
+
+ if (result != 0)
+ ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "ACE_Predefined_Naming_Contexts::connect failed"), -1);
+
+ // Print contents of naming context
+ result = ::print_naming_context (naming_context, 0);
+ if (result != 0)
+ ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "print_naming_context failed"), -1);
+
+ return 0;
+}
+
+
+// Print contents of <naming_context>
+static int
+print_naming_context (ACE_Registry::Naming_Context &naming_context,
+ u_long indentation)
+{
+ ACE_Registry::Binding_List list;
+
+ // Get the list of all entries
+ int result = naming_context.list (list);
+ if (result != 0)
+ ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "ACE_Registry::Naming_Context::list"), -1);
+
+ // Iterator through all entries
+ for (ACE_Registry::Binding_List::iterator i = list.begin ();
+ i != list.end ();
+ ++i)
+ {
+ // Yeeesss! STL rules!
+ ACE_Registry::Binding &binding = *i;
+
+ if (binding.type () == ACE_Registry::OBJECT)
+ // If object
+ ::print_object (binding.name (),
+ indentation);
+ else
+ // If context
+ ::print_context (naming_context,
+ binding.name (),
+ indentation);
+ }
+ return 0;
+}
+
+
+// Print an object with <name>
+static void
+print_object (const ACE_TString &name,
+ u_long indentation)
+{
+ // Set indentation
+ ::indent (indentation);
+ cout << name << endl;
+}
+
+
+// Print an context with <name> and <parent>
+static void
+print_context (ACE_Registry::Naming_Context &parent,
+ const ACE_TString &name,
+ u_long indentation)
+{
+ // Set indentation
+ indent (indentation);
+ cout << name << endl;
+
+ ACE_Registry::Naming_Context child_context;
+ // Find child context
+ int result = parent.resolve_context (name,
+ child_context,
+ KEY_READ);
+ if (result != 0)
+ ACE_ERROR ((LM_ERROR, "%s %s\n", "ACE_Registry::Naming_Context::resolve_context failed for:", name.c_str ()));
+ else
+ {
+ // Print contents of the child
+ result = ::print_naming_context (child_context,
+ indentation + INDENTATION_LEVEL);
+ if (result != 0)
+ ACE_ERROR ((LM_ERROR, "%p\n", "print_naming_context failed"));
+ }
+}
+
+
+// Pretty formating
+static void
+indent (u_long indentation)
+{
+ for (; indentation > 0; indentation--)
+ cout << " ";
+}
+#else /* !ACE_WIN32 */
+int
+ACE_TMAIN (int , ACE_TCHAR *[])
+{
+ return 0;
+}
+#endif /* ACE_WIN32 */
diff --git a/ACE/examples/Registry/test_registry_update.cpp b/ACE/examples/Registry/test_registry_update.cpp
new file mode 100644
index 00000000000..443f1a766ff
--- /dev/null
+++ b/ACE/examples/Registry/test_registry_update.cpp
@@ -0,0 +1,161 @@
+// $Id$
+
+// Suppose this application belonged to AcmeSoft. AcmeSoft wants to
+// keep track of the number of times this application is
+// executed. They want two counters: one counts the number of
+// executions per machine, the other keeps track of the number of
+// executions per user.
+//
+// This application uses the ACE_Registry class to create and update
+// entries in the LOCAL_MACHINE and CURRENT_USER predefined registries
+// to store the counters.
+//
+// Note that this application will not work with remote registries
+// if used with the CURRENT_USER predefined registry.
+
+#include "ace/OS_main.h"
+
+#if defined (ACE_WIN32)
+
+#include "ace/Registry.h"
+
+// FUZZ: disable check_for_streams_include
+#include "ace/streams.h"
+
+ACE_RCSID(Registry, test_registry_update, "$Id$")
+
+// Name for application's naming context
+static ACE_Registry::Name application_context_name;
+
+// Name for instance counter.
+static ACE_Registry::Name counter_name;
+
+// Protypes
+static int update_counter (HKEY predefined,
+ u_long &current_counter);
+static void setup_names ();
+
+int
+ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ int result;
+ u_long current_counter = 0;
+
+ // initialize name
+ setup_names ();
+
+ // Update counter per user
+ result = ::update_counter (HKEY_CURRENT_USER,
+ current_counter);
+ if (result == 0)
+ {
+ cout << "User counter: " << current_counter << endl;
+
+ // Update counter per machine
+ result = ::update_counter (HKEY_LOCAL_MACHINE,
+ current_counter);
+ if (result == 0)
+ cout << "Machine counter: " << current_counter << endl;
+ }
+
+ if (result != 0)
+ ACE_DEBUG ((LM_DEBUG, "test failed\n"));
+ else
+ ACE_DEBUG ((LM_DEBUG, "test succeeded\n"));
+
+ return 0;
+}
+
+static int
+update_counter (HKEY predefined,
+ u_long &current_counter)
+{
+ int result;
+ ACE_Registry::Naming_Context parent_context;
+ ACE_Registry::Naming_Context application_context;
+
+ // Connect to predefined entry
+ result = ACE_Predefined_Naming_Contexts::connect (parent_context,
+ predefined);
+ if (result != 0)
+ ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "ACE_Predefined_Naming_Contexts::connect failed"), -1);
+
+ // Find application context name
+ result = parent_context.resolve_context (application_context_name,
+ application_context);
+
+ if (result != 0)
+ // Failed to find: create a new context
+ result = parent_context.bind_new_context (application_context_name,
+ application_context);
+
+ if (result != 0)
+ ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "ACE_Registry::Naming_Contexts::bind/resolve_context failed"), -1);
+
+ // Counter
+ u_long counter = 0;
+ // Represent counter as an ACE_Registry::Object
+ ACE_Registry::Object object ((void *) &counter,
+ sizeof counter,
+ REG_DWORD);
+ // Find counter
+ result = application_context.resolve (counter_name,
+ object);
+
+ if (result != 0)
+ // Failed to find: create new binding for object
+ {
+ counter = 1;
+ result = application_context.bind (counter_name,
+ object);
+ }
+ else
+ // Counter was found
+ {
+ // increment counter
+ counter++;
+ // Update
+ result = application_context.rebind (counter_name,
+ object);
+ }
+
+ if (result != 0)
+ ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "ACE_Registry::Naming_Contexts::bind/resolve failed"), -1);
+ else
+ current_counter = counter;
+
+ return 0;
+}
+
+
+static void
+setup_names ()
+{
+ // Stupid implementation of STL is broken
+ /*
+ ::application_context_name.reserve (4);
+ ::application_context_name [0].id_ = ACE_TEXT ("Software");
+ ::application_context_name [1].id_ = ACE_TEXT ("AcmeSoft");
+ ::application_context_name [2].id_ = ACE_TEXT ("AcmeApplication");
+ ::application_context_name [3].id_ = ACE_TEXT ("1.0");
+
+ ::counter_name.reserve (1);
+ ::counter_name [0].id_ = ACE_TEXT ("Instance Counter");
+ */
+
+ ACE_Registry::Name_Component component;
+
+ component.id_ = ACE_TEXT ("Software"), ::application_context_name.insert (component);
+ component.id_ = ACE_TEXT ("AcmeSoft"), ::application_context_name.insert (component);
+ component.id_ = ACE_TEXT ("AcmeApplication"), ::application_context_name.insert (component);
+ component.id_ = ACE_TEXT ("1.0"), ::application_context_name.insert (component);
+
+ component.id_ = ACE_TEXT ("Instance Counter"), ::counter_name.insert (component);
+}
+#else /* !ACE_WIN32 */
+int
+ACE_TMAIN (int , ACE_TCHAR *[])
+{
+ return 0;
+}
+#endif /* ACE_WIN32 */
diff --git a/ACE/examples/Service_Configurator/IPC-tests/Makefile.am b/ACE/examples/Service_Configurator/IPC-tests/Makefile.am
new file mode 100644
index 00000000000..0a99932ce34
--- /dev/null
+++ b/ACE/examples/Service_Configurator/IPC-tests/Makefile.am
@@ -0,0 +1,14 @@
+## Process this file with automake to create Makefile.in
+##
+## $Id$
+##
+## This file was generated by MPC. Any changes made directly to
+## this file will be lost the next time it is generated.
+##
+## MPC Command:
+## /acebuilds/ACE_wrappers-repository/bin/mwc.pl -include /acebuilds/MPC/config -include /acebuilds/MPC/templates -feature_file /acebuilds/ACE_wrappers-repository/local.features -noreldefs -type automake -exclude build,Kokyu
+
+SUBDIRS = \
+ client \
+ server
+
diff --git a/ACE/examples/Service_Configurator/IPC-tests/README b/ACE/examples/Service_Configurator/IPC-tests/README
new file mode 100644
index 00000000000..6f491296af7
--- /dev/null
+++ b/ACE/examples/Service_Configurator/IPC-tests/README
@@ -0,0 +1,125 @@
+This file describes how to invoke the tests in the
+$ACE_ROOT/examples/Service_Configurator/IPC-test/{client,server}
+directories. These tests exercise all of the ACE IPC SAP
+communication mechanisms, the Reactor event demultiplexor, and the
+Service Configurator dynamic service configuration framework. To gain
+a deeper understanding of what is going on, you should read the the
+Wrapper Facade, Reactor, and Component Configurator patterns in POSA2
+<http://www.cs.wustl.edu/~schmidt/POSA/> and check out the following
+papers on the ACE framework components:
+
+http://www.cs.wustl.edu/~schmidt/PDF/IPC_SAP-92.pdf
+http://www.cs.wustl.edu/~schmidt/PDF/Reactor1-93.pdf
+http://www.cs.wustl.edu/~schmidt/PDF/Reactor2-93.pdf
+http://www.cs.wustl.edu/~schmidt/PDF/reactor-rules.pdf
+http://www.cs.wustl.edu/~schmidt/PDF/Svc-Conf.pdf
+
+The key to running these client/server tests is to understand the
+purpose of the svc.conf file located in the
+$ACE_ROOT/examples/Service_Configurator/IPC-test/server/ directory.
+This file contains a list of services that may be dynamically
+configured into a the address space of a network daemon process. If
+you look at the example svc.conf file included in the tests you'll see
+that some entries are commented out (the comment symbol is the '#',
+which is an "ignore until end-of-line comment" with the same semantics
+as the UNIX C and Bourne shells). Before reading any further, take a
+look at this svc.conf file with your favorite editor or file browser.
+
+There are several types of entries in this file. The two most
+important are the lines beginning with the keywords "static" and
+"dynamic". For example, the first non-commented line says:
+
+static ACE_Service_Manager "-d -p 3911"
+
+When this line is parsed at startup time by the Service Configurator
+object in the ./server_test executable, it causes the pre-configured
+Svc_Manager object to be initialized with an "argv" argument of "-d -p
+3911." This results in TCP port 3911 being created to listen
+connection requests from clients. To see how this works do the
+following:
+
+1. Comment out all the other lines except
+
+ static Svc_Manager "-d -p 3911"
+
+ in the svc.conf file
+
+2. Start up the ./server_test executable in one window, as follows:
+
+ % ./server_test -d
+
+3. Make another window on the *same* host and cd to the ./client/
+ directory
+
+4. Run the ./remote_service_directory_test program as follows:
+
+ % ./remote_service_directory_test -p 3911 -h localhost
+
+If everything has been compiled and initialized correctly, you should
+get the following message:
+
+ Svc_Manager 3911/tcp # lists all services in the daemon
+
+This message is telling you that the Svc_Manager is currently the only
+service that is active within the ./server_test program. To configure
+and activate another service dynamically, perform the following steps:
+
+1. *Without* shutting down the ./server_test program, edit the svc.conf
+ file. Comment out the Svc_Manager line by adding a '#' at the
+ front, i.e.:
+
+ # static Svc_Manager "-d -p 3911"
+
+ and then uncomment the second line:
+
+ dynamic Remote_Brdcast Service_Object * ./IPC_Tests_Server:remote_broadcast "-p 10001"
+
+2. If you're running on an OS platform that supports SIGHUP, send the
+ SIGHUP signal to the process running the ./server_test program.
+ This will cause the ./server_test program to reconfigure itself
+ based on the new contents of the svc.conf file. Not every platform
+ supports SIGHUP. However, the remote_service_directory_test in
+ ./client/ can be used to reconfigure services, e.g., by passing it
+ parameters as follows:
+
+ % ./remote_service_directory_test -p 3911 -h localhost -r
+
+ The '-r' flag instructs the server to reconfigure itself.
+
+ After reconfiguration, you'll now have a second active service in
+ the address space of the ./server_test daemon. To see this, rerun
+ the remote_service_directory_test command, e.g.:
+
+ % ./remote_service_directory_test -p 3911 -h localhost
+
+ You should now see the following output:
+
+ Svc_Manager 3911/tcp # lists all services in the daemon
+ Remote_Brdcast 10001/udp # tests broadcasting
+
+ which indicates that the remote broadcast service is now active.
+
+3. To test the remote broadcast service, run the following program
+ in the ./client/ directory:
+
+ % ./broadcast_client_test -p 10001
+
+ This should cause the window running the ./server_test to
+ display the following output:
+
+ received broadcast datagram from host spare.ics.uci.edu
+ ----------------------------------------
+ testing socket broadcast service
+ ----------------------------------------
+
+If you want to run other tests, using other configurations, simply
+uncomment the appropriate lines in the svc.conf file and experiment
+with the corresponding test drivers in the ./client/ directory. All
+the source code is available so once you get the hang of what is
+happening, you might want to take a look at how it is all implemented.
+You may be surprised at how much of the ACE framework code is
+reused for each different service. Moreover, writing a new service is
+often simply a matter of copying an existing file and filling in the
+behavior of some of the methods (e.g., the handle_input() method and
+the init() method).
+
diff --git a/ACE/examples/Service_Configurator/IPC-tests/client/.cvsignore b/ACE/examples/Service_Configurator/IPC-tests/client/.cvsignore
new file mode 100644
index 00000000000..121d4de020f
--- /dev/null
+++ b/ACE/examples/Service_Configurator/IPC-tests/client/.cvsignore
@@ -0,0 +1,10 @@
+local_dgram_test
+local_fifo_test
+local_pipe_test
+local_spipe_test
+local_stream_test
+remote_broadcast_test
+remote_dgram_test
+remote_service_directory_test
+remote_stream_test
+remote_thr_stream_test
diff --git a/ACE/examples/Service_Configurator/IPC-tests/client/Makefile.am b/ACE/examples/Service_Configurator/IPC-tests/client/Makefile.am
new file mode 100644
index 00000000000..b6dd5a3d7b8
--- /dev/null
+++ b/ACE/examples/Service_Configurator/IPC-tests/client/Makefile.am
@@ -0,0 +1,180 @@
+## Process this file with automake to create Makefile.in
+##
+## $Id$
+##
+## This file was generated by MPC. Any changes made directly to
+## this file will be lost the next time it is generated.
+##
+## MPC Command:
+## /acebuilds/ACE_wrappers-repository/bin/mwc.pl -include /acebuilds/MPC/config -include /acebuilds/MPC/templates -feature_file /acebuilds/ACE_wrappers-repository/local.features -noreldefs -type automake -exclude build,Kokyu
+
+ACE_BUILDDIR = $(top_builddir)
+ACE_ROOT = $(top_srcdir)
+
+noinst_PROGRAMS =
+
+## Makefile.Svc_Cfg_IPC_Client_Bcast.am
+
+if !BUILD_ACE_FOR_TAO
+noinst_PROGRAMS += remote_broadcast_test
+
+remote_broadcast_test_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+remote_broadcast_test_SOURCES = \
+ broadcast_client_test.cpp
+
+remote_broadcast_test_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+endif !BUILD_ACE_FOR_TAO
+
+## Makefile.Svc_Cfg_IPC_Client_Loc_Dgram.am
+
+if !BUILD_ACE_FOR_TAO
+noinst_PROGRAMS += local_dgram_test
+
+local_dgram_test_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+local_dgram_test_SOURCES = \
+ local_dgram_client_test.cpp
+
+local_dgram_test_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+endif !BUILD_ACE_FOR_TAO
+
+## Makefile.Svc_Cfg_IPC_Client_Loc_Fifo.am
+
+if !BUILD_ACE_FOR_TAO
+noinst_PROGRAMS += local_fifo_test
+
+local_fifo_test_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+local_fifo_test_SOURCES = \
+ local_fifo_client_test.cpp
+
+local_fifo_test_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+endif !BUILD_ACE_FOR_TAO
+
+## Makefile.Svc_Cfg_IPC_Client_Loc_Pipe.am
+
+if !BUILD_ACE_FOR_TAO
+noinst_PROGRAMS += local_pipe_test
+
+local_pipe_test_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+local_pipe_test_SOURCES = \
+ local_pipe_client_test.cpp
+
+local_pipe_test_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+endif !BUILD_ACE_FOR_TAO
+
+## Makefile.Svc_Cfg_IPC_Client_Loc_Spipe.am
+noinst_PROGRAMS += local_spipe_test
+
+local_spipe_test_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+local_spipe_test_SOURCES = \
+ local_spipe_client_test.cpp
+
+local_spipe_test_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Makefile.Svc_Cfg_IPC_Client_Loc_Stream.am
+
+if !BUILD_ACE_FOR_TAO
+noinst_PROGRAMS += local_stream_test
+
+local_stream_test_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+local_stream_test_SOURCES = \
+ local_stream_client_test.cpp
+
+local_stream_test_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+endif !BUILD_ACE_FOR_TAO
+
+## Makefile.Svc_Cfg_IPC_Client_Rem_Dgram.am
+
+if !BUILD_ACE_FOR_TAO
+noinst_PROGRAMS += remote_dgram_test
+
+remote_dgram_test_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+remote_dgram_test_SOURCES = \
+ remote_dgram_client_test.cpp
+
+remote_dgram_test_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+endif !BUILD_ACE_FOR_TAO
+
+## Makefile.Svc_Cfg_IPC_Client_Rem_Stream.am
+
+if !BUILD_ACE_FOR_TAO
+noinst_PROGRAMS += remote_stream_test
+
+remote_stream_test_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+remote_stream_test_SOURCES = \
+ remote_stream_client_test.cpp
+
+remote_stream_test_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+endif !BUILD_ACE_FOR_TAO
+
+## Makefile.Svc_Cfg_IPC_Client_Rem_Svc_Dir.am
+noinst_PROGRAMS += remote_service_directory_test
+
+remote_service_directory_test_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+remote_service_directory_test_SOURCES = \
+ remote_service_directory_test.cpp
+
+remote_service_directory_test_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Makefile.Svc_Cfg_IPC_Client_Rem_Thr_Stream.am
+noinst_PROGRAMS += remote_thr_stream_test
+
+remote_thr_stream_test_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+remote_thr_stream_test_SOURCES = \
+ remote_thr_stream_client_test.cpp
+
+remote_thr_stream_test_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Clean up template repositories, etc.
+clean-local:
+ -rm -f *~ *.bak *.rpo *.sym lib*.*_pure_* core core.*
+ -rm -f gcctemp.c gcctemp so_locations *.ics
+ -rm -rf cxx_repository ptrepository ti_files
+ -rm -rf templateregistry ir.out
+ -rm -rf ptrepository SunWS_cache Templates.DB
diff --git a/ACE/examples/Service_Configurator/IPC-tests/client/Svc_Cfg_IPC_Client.mpc b/ACE/examples/Service_Configurator/IPC-tests/client/Svc_Cfg_IPC_Client.mpc
new file mode 100644
index 00000000000..6876c4aac4d
--- /dev/null
+++ b/ACE/examples/Service_Configurator/IPC-tests/client/Svc_Cfg_IPC_Client.mpc
@@ -0,0 +1,70 @@
+// -*- MPC -*-
+// $Id$
+
+project(*loc dgram) : aceexe {
+ avoids += ace_for_tao
+ exename = local_dgram_test
+ Source_Files {
+ local_dgram_client_test.cpp
+ }
+}
+project(*loc fifo) : aceexe {
+ avoids += ace_for_tao
+ exename = local_fifo_test
+ Source_Files {
+ local_fifo_client_test.cpp
+ }
+}
+project(*loc pipe) : aceexe {
+ avoids += ace_for_tao
+ exename = local_pipe_test
+ Source_Files {
+ local_pipe_client_test.cpp
+ }
+}
+project(*loc spipe) : aceexe {
+ exename = local_spipe_test
+ Source_Files {
+ local_spipe_client_test.cpp
+ }
+}
+project(*loc stream) : aceexe {
+ avoids += ace_for_tao
+ exename = local_stream_test
+ Source_Files {
+ local_stream_client_test.cpp
+ }
+}
+project(*rem dgram) : aceexe {
+ avoids += ace_for_tao
+ exename = remote_dgram_test
+ Source_Files {
+ remote_dgram_client_test.cpp
+ }
+}
+project(*rem svc dir) : aceexe {
+ exename = remote_service_directory_test
+ Source_Files {
+ remote_service_directory_test.cpp
+ }
+}
+project(*rem stream) : aceexe {
+ avoids += ace_for_tao
+ exename = remote_stream_test
+ Source_Files {
+ remote_stream_client_test.cpp
+ }
+}
+project(*rem thr_stream) : aceexe {
+ exename = remote_thr_stream_test
+ Source_Files {
+ remote_thr_stream_client_test.cpp
+ }
+}
+project(*bcast) : aceexe {
+ avoids += ace_for_tao
+ exename = remote_broadcast_test
+ Source_Files {
+ broadcast_client_test.cpp
+ }
+}
diff --git a/ACE/examples/Service_Configurator/IPC-tests/client/broadcast_client_test.cpp b/ACE/examples/Service_Configurator/IPC-tests/client/broadcast_client_test.cpp
new file mode 100644
index 00000000000..4cbb964cd74
--- /dev/null
+++ b/ACE/examples/Service_Configurator/IPC-tests/client/broadcast_client_test.cpp
@@ -0,0 +1,62 @@
+// $Id$
+
+// Tests out the broadcast service of the
+// Internet domain IPC-SAP dgram abstraction.
+
+#include "ace/OS_main.h"
+#include "ace/OS_NS_stdio.h"
+#include "ace/OS_NS_string.h"
+#include "ace/OS_NS_stdlib.h"
+#include "ace/INET_Addr.h"
+#include "ace/SOCK_Dgram_Bcast.h"
+#include "ace/Get_Opt.h"
+#include "ace/Log_Msg.h"
+
+ACE_RCSID(client, broadcast_client_test, "$Id$")
+
+/* Name of the program. */
+static ACE_TCHAR *program_name;
+
+/* Port number to use. */
+static unsigned short broadcast_port_number = ACE_DEFAULT_BROADCAST_PORT;
+
+static void
+print_usage_and_die (void)
+{
+ ACE_OS::fprintf (stderr, "usage: %s [-p broadcast portnum]\n",
+ program_name);
+ ACE_OS::exit (1);
+}
+
+void
+parse_args (int argc, ACE_TCHAR *argv[])
+{
+ ACE_Get_Opt get_opt (argc, argv, ACE_TEXT("p:"));
+
+ for (int c; (c = get_opt ()) != -1; )
+ switch (c)
+ {
+ case 'p':
+ broadcast_port_number = ACE_OS::atoi (get_opt.opt_arg ());
+ break;
+ default:
+ print_usage_and_die ();
+ break;
+ }
+}
+
+int
+ACE_TMAIN (int argc, ACE_TCHAR *argv[])
+{
+ program_name = argv[0];
+ parse_args (argc, argv);
+
+ ACE_SOCK_Dgram_Bcast sd (ACE_Addr::sap_any);
+
+ static char buf[] = "testing socket broadcast service";
+
+ if (sd.send (buf, ACE_OS::strlen (buf), broadcast_port_number) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "can't send broadcast"), -1);
+
+ return 0;
+}
diff --git a/ACE/examples/Service_Configurator/IPC-tests/client/local_data b/ACE/examples/Service_Configurator/IPC-tests/client/local_data
new file mode 100644
index 00000000000..1faba1b8091
--- /dev/null
+++ b/ACE/examples/Service_Configurator/IPC-tests/client/local_data
@@ -0,0 +1,22 @@
+locallocallocallocallocallocallocallocal
+locallocallocallocallocallocallocallocal
+locallocallocallocallocallocallocallocal
+locallocallocallocallocallocallocallocal
+locallocallocallocallocallocallocallocal
+locallocallocallocallocallocallocallocal
+locallocallocallocallocallocallocallocal
+locallocallocallocallocallocallocallocal
+locallocallocallocallocallocallocallocal
+locallocallocallocallocallocallocallocal
+locallocallocallocallocallocallocallocal
+locallocallocallocallocallocallocallocal
+locallocallocallocallocallocallocallocal
+locallocallocallocallocallocallocallocal
+locallocallocallocallocallocallocallocal
+locallocallocallocallocallocallocallocal
+locallocallocallocallocallocallocallocal
+locallocallocallocallocallocallocallocal
+locallocallocallocallocallocallocallocal
+locallocallocallocallocallocallocallocal
+locallocallocallocallocallocallocallocal
+locallocallocallocallocallocallocallocal
diff --git a/ACE/examples/Service_Configurator/IPC-tests/client/local_dgram_client_test.cpp b/ACE/examples/Service_Configurator/IPC-tests/client/local_dgram_client_test.cpp
new file mode 100644
index 00000000000..3f8ed3db866
--- /dev/null
+++ b/ACE/examples/Service_Configurator/IPC-tests/client/local_dgram_client_test.cpp
@@ -0,0 +1,117 @@
+// $Id$
+
+// Tests out the UNIX domain IPC-SAP abstraction.
+
+#include "ace/OS_main.h"
+#include "ace/LSOCK_CODgram.h"
+#include "ace/LSOCK_Dgram.h"
+#include "ace/UNIX_Addr.h"
+#include "ace/Get_Opt.h"
+#include "ace/OS_NS_string.h"
+#include "ace/OS_NS_stdio.h"
+#include "ace/OS_NS_stdlib.h"
+#include "ace/OS_NS_unistd.h"
+#include "ace/OS_NS_fcntl.h"
+
+ACE_RCSID(client, local_dgram_client_test, "$Id$")
+
+#if defined (ACE_HAS_MSG) && !defined (ACE_LACKS_UNIX_DOMAIN_SOCKETS)
+// Name of the program.
+static ACE_TCHAR *program_name;
+
+// Name of rendezvous point.
+static const ACE_TCHAR *rendezvous_codgram = ACE_TEXT ("/tmp/foo_codgram");
+static const ACE_TCHAR *rendezvous_dgram = ACE_TEXT ("/tmp/foo_dgram");
+
+// Name of file to send.
+static const ACE_TCHAR *file_name = ACE_TEXT ("local_data");
+
+static void
+print_usage_and_die (void)
+{
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("usage: %s [-r rendezvous_dgram] ")
+ ACE_TEXT ("[-c rendezvous_codgram] [-f file]\n"),
+ program_name));
+ ACE_OS::exit (1);
+}
+
+void
+parse_args (int argc, ACE_TCHAR *argv[])
+{
+ ACE_Get_Opt get_opt (argc, argv, ACE_TEXT ("c:f:r:"));
+
+ for (int c; (c = get_opt ()) != -1; )
+ switch (c)
+ {
+ case 'f':
+ file_name = get_opt.opt_arg ();
+ break;
+ case 'r':
+ rendezvous_dgram = get_opt.opt_arg ();
+ break;
+ case 'c':
+ rendezvous_codgram = get_opt.opt_arg ();
+ break;
+ default:
+ print_usage_and_die ();
+ break;
+ }
+}
+
+int
+ACE_TMAIN (int argc, ACE_TCHAR *argv[])
+{
+ program_name = argv[0];
+
+ parse_args (argc, argv);
+
+ char *sock_client = ACE_OS::tempnam ();
+
+ ACE_LSOCK_Dgram sd ((ACE_UNIX_Addr) (sock_client));
+ if (ACE_OS::unlink (sock_client))
+ ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("%p\n"), ACE_TEXT ("unlink")),
+ -1);
+ ACE_OS::free ((void *) sock_client);
+
+ ACE_LSOCK_CODgram sc;
+
+ if (sc.open (ACE_UNIX_Addr (rendezvous_codgram),
+ ACE_Addr::sap_any) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("%p\n"), ACE_TEXT ("open")),
+ -1);
+
+ ACE_HANDLE handle = ACE_OS::open (file_name, O_RDONLY);
+
+ if (handle == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("%p\n"), ACE_TEXT ("open")),
+ -1);
+
+ // Send the open file descriptor to the server!
+
+ if (sc.send_handle (handle) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("%p\n"), ACE_TEXT ("send")),
+ -1);
+
+ char name[ACE_MAX_USERID];
+ ACE_OS::cuserid (name);
+
+ if (sd.send (name,
+ ACE_OS::strlen (name) + 1,
+ ACE_UNIX_Addr (rendezvous_dgram)) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("%p\n"), ACE_TEXT ("send")),
+ -1);
+
+ if (ACE_OS::close (handle) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("%p\n"), ACE_TEXT ("close")),
+ -1);
+ return 0;
+}
+#else
+int ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("your platform must support sendmsg/recvmsg to run this test\n")),
+ -1);
+}
+#endif /* ACE_HAS_MSG */
diff --git a/ACE/examples/Service_Configurator/IPC-tests/client/local_fifo_client_test.cpp b/ACE/examples/Service_Configurator/IPC-tests/client/local_fifo_client_test.cpp
new file mode 100644
index 00000000000..9fb26b4088e
--- /dev/null
+++ b/ACE/examples/Service_Configurator/IPC-tests/client/local_fifo_client_test.cpp
@@ -0,0 +1,101 @@
+// $Id$
+
+// Send a file through ACE_FIFO communication channel by
+// breaking it (the file) into pieces.
+
+#include "ace/OS_main.h"
+#include "ace/Mem_Map.h"
+#include "ace/FIFO_Send_Msg.h"
+#include "ace/Get_Opt.h"
+#include "ace/Log_Msg.h"
+#include "ace/OS_NS_stdlib.h"
+#include "ace/OS_NS_stropts.h"
+
+ACE_RCSID(client, local_fifo_client_test, "$Id$")
+
+// Name of the program.
+static ACE_TCHAR *program_name;
+
+// debug state on or off
+static int debug = 0;
+
+static const ACE_TCHAR *rendezvous_fifo = ACE_TEXT("/tmp/foo_fifo");
+
+// Name of file to send.
+static const ACE_TCHAR *file_name = ACE_TEXT("./local_data");
+
+static void
+print_usage_and_die (void)
+{
+ ACE_ERROR ((LM_ERROR,
+ "usage: %s [-d] [-f rendezvous_fifo]\n",
+ program_name));
+ ACE_OS::exit (1);
+}
+
+static void
+parse_arguments (int argc, ACE_TCHAR *argv[])
+{
+ int tracing = 1;
+ program_name = argv[0];
+
+ ACE_Get_Opt get_opt (argc, argv, ACE_TEXT("df:"));
+
+ for (int c; (c = get_opt ()) != -1; )
+ switch (c)
+ {
+ case 'd':
+ debug = 1;
+ break;
+ case 'f':
+ rendezvous_fifo = get_opt.opt_arg ();
+ break;
+ default:
+ print_usage_and_die ();
+ break;
+ }
+
+ if (debug)
+ ACE_DEBUG ((LM_DEBUG,
+ "rendezvous_fifo = %s\n"
+ "trace = %s\n",
+ rendezvous_fifo,
+ tracing ? "on" : "off"));
+}
+
+int
+ACE_TMAIN(int argc, ACE_TCHAR *argv[])
+{
+ parse_arguments (argc, argv);
+
+ ACE_FIFO_Send_Msg fifo;
+
+ if (fifo.open (rendezvous_fifo,
+ O_WRONLY,
+ 0666) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Cannot open %s for requesting a new communication channel"
+ "in local_fifo_client_test\n",
+ rendezvous_fifo),
+ -1);
+ void *cp = 0;
+ ACE_Mem_Map mmap (file_name);
+
+ if (mmap (cp) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%p\n",
+ "mmap"),
+ -1);
+
+ // Next, send the file's contents.
+
+ ACE_Str_Buf msg (cp,
+ int (mmap.size ()));
+
+ if (fifo.send (msg) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%p\n",
+ "send"),
+ -1);
+ return 0;
+}
diff --git a/ACE/examples/Service_Configurator/IPC-tests/client/local_pipe_client_test.cpp b/ACE/examples/Service_Configurator/IPC-tests/client/local_pipe_client_test.cpp
new file mode 100644
index 00000000000..7193440b440
--- /dev/null
+++ b/ACE/examples/Service_Configurator/IPC-tests/client/local_pipe_client_test.cpp
@@ -0,0 +1,150 @@
+// $Id$
+
+// Another test of UNIX domain IPC-SAP abstraction. This one opens 2
+// pipes and then ships certain ends over to the server to act as a
+// filter!
+
+#include "ace/OS_main.h"
+#include "ace/LSOCK_Connector.h"
+#include "ace/UNIX_Addr.h"
+#include "ace/Get_Opt.h"
+#include "ace/OS_NS_stdlib.h"
+#include "ace/OS_NS_unistd.h"
+#include "ace/OS_NS_fcntl.h"
+
+ACE_RCSID(client, local_pipe_client_test, "$Id$")
+
+#if defined (ACE_HAS_MSG) && !defined (ACE_LACKS_UNIX_DOMAIN_SOCKETS)
+// Name of the program.
+static ACE_TCHAR *program_name;
+
+// Name of rendezvous point.
+static const ACE_TCHAR *rendezvous = ACE_TEXT ("/tmp/foo_pipe");
+
+// Name of file to send.
+static const ACE_TCHAR *file_name = ACE_TEXT ("local_data");
+
+static void
+print_usage_and_die (void)
+{
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("usage: %s [-r rendezvous] [-f file]\n"),
+ program_name));
+ ACE_OS::exit (1);
+}
+
+void
+parse_args (int argc, ACE_TCHAR *argv[])
+{
+ program_name = argv[0];
+
+ ACE_Get_Opt get_opt (argc, argv, ACE_TEXT ("f:r:"));
+
+ for (int c; (c = get_opt ()) != -1; )
+ switch (c)
+ {
+ case 'f':
+ file_name = get_opt.opt_arg ();
+ break;
+ case 'r':
+ rendezvous = get_opt.opt_arg ();
+ break;
+ default:
+ print_usage_and_die ();
+ break;
+ }
+}
+
+static int
+do_client_processing (ACE_LSOCK_Stream &sc)
+{
+ ACE_HANDLE fd_read[2];
+ ACE_HANDLE fd_write[2];
+ char buf[BUFSIZ];
+ int n;
+
+ if (ACE_OS::pipe (fd_read) == -1 || ACE_OS::pipe (fd_write) == -1)
+ return -1;
+
+ if (sc.send_handle (fd_write[0]) == -1 || sc.send_handle (fd_read[1]) == -1)
+ return -1;
+
+ // Close off the ends we aren't interested in.
+
+ if (ACE_OS::close (fd_read[1]) || ACE_OS::close (fd_write[0]) == -1)
+ return -1;
+
+ // Do a silly dup just for fun...
+
+ ACE_HANDLE fd1 = ACE_OS::open (file_name, O_RDONLY);
+
+ if (fd1 == ACE_INVALID_HANDLE)
+ return -1;
+
+ while ((n = ACE_OS::read (fd1, buf, sizeof buf)) > 0)
+ {
+ if (ACE_OS::write (fd_write[1],
+ buf,
+ n) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("write")),
+ -1);
+ if ((n = ACE_OS::read (fd_read[0],
+ buf,
+ sizeof buf)) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("read")),
+ -1);
+ if (ACE_OS::write (ACE_STDOUT,
+ buf,
+ n) == -1)
+ return -1;
+ }
+
+ if (ACE_OS::close (fd_read[0]) == -1
+ || ACE_OS::close (fd_write[1]) == -1
+ || ACE_OS::close (fd1) == -1)
+ ACE_OS::exit (1);
+
+ return 0;
+}
+
+int
+ACE_TMAIN (int argc, ACE_TCHAR *argv[])
+{
+ parse_args (argc, argv);
+
+ ACE_LSOCK_Stream sc;
+ ACE_LSOCK_Connector con;
+
+ if (con.connect (sc,
+ ACE_UNIX_Addr (rendezvous)) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("connect")),
+ -1);
+
+ if (do_client_processing (sc) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("do_client_processing")),
+ -1);
+
+ if (sc.close () == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("close")),
+ -1);
+
+ return 0;
+}
+#else
+int ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("your platform must support sendmsg/recvmsg to run this test\n")),
+ -1);
+}
+#endif /* ACE_HAS_MSG */
diff --git a/ACE/examples/Service_Configurator/IPC-tests/client/local_spipe_client_test.cpp b/ACE/examples/Service_Configurator/IPC-tests/client/local_spipe_client_test.cpp
new file mode 100644
index 00000000000..91d81338ea1
--- /dev/null
+++ b/ACE/examples/Service_Configurator/IPC-tests/client/local_spipe_client_test.cpp
@@ -0,0 +1,106 @@
+// $Id$
+
+// Send a file through ACE_SPIPE communication channel by
+// breaking it (the file) into pieces.
+
+#include "ace/OS_main.h"
+#include "ace/Mem_Map.h"
+#include "ace/SPIPE_Connector.h"
+#include "ace/Get_Opt.h"
+#include "ace/Log_Msg.h"
+
+ACE_RCSID(client, local_spipe_client_test, "$Id$")
+
+#if defined (ACE_HAS_STREAM_PIPES)
+
+static ACE_TCHAR *program_name;
+
+// debug state on or off
+static int debug = 0;
+
+static const ACE_TCHAR *rendezvous_spipe = ACE_TEXT ("/tmp/foo_spipe");
+
+// Name of file to send.
+static const ACE_TCHAR *file_name = ACE_TEXT ("./local_data");
+
+static void
+print_usage_and_die (void)
+{
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("usage: %s [-d] [-r rendezvous_spipe]\n"),
+ program_name));
+ ACE_OS::exit (1);
+}
+
+static void
+parse_arguments (int argc, ACE_TCHAR *argv[])
+{
+ program_name = argv[0];
+ ACE_Get_Opt get_opt (argc, argv, ACE_TEXT ("dr:"));
+
+ for (int c; (c = get_opt ()) != -1; )
+ switch (c)
+ {
+ case 'd':
+ debug = 1;
+ break;
+ case 'r':
+ rendezvous_spipe = get_opt.opt_arg ();
+ break;
+ default:
+ print_usage_and_die ();
+ break;
+ }
+ if (debug)
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("rendezvous_spipe = %s\n"),
+ rendezvous_spipe));
+}
+
+int
+ACE_TMAIN(int argc, ACE_TCHAR *argv[])
+{
+ parse_arguments (argc, argv);
+
+ ACE_SPIPE_Stream spipe;
+ ACE_SPIPE_Connector con;
+
+ if (con.connect (spipe,
+ ACE_SPIPE_Addr (rendezvous_spipe)) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("Cannot open %s for requesting a new ")
+ ACE_TEXT ("communication channel in %p\n"),
+ rendezvous_spipe,
+ ACE_TEXT ("local_spipe_client_test")),
+ -1);
+
+ ACE_Mem_Map mmap (file_name);
+ void *cp;
+
+ if (mmap (cp) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("mmap")),
+ -1);
+
+ // Next, send the file's contents.
+
+ ACE_Str_Buf msg (cp, int (mmap.size ()));
+
+ if (spipe.send ((ACE_Str_Buf *) 0, &msg) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("send")),
+ -1);
+ return 0;
+}
+#else
+#include <stdio.h>
+int
+ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("This feature is not supported\n")),
+ -1);
+}
+#endif /* ACE_HAS_STREAM_PIPES */
diff --git a/ACE/examples/Service_Configurator/IPC-tests/client/local_stream_client_test.cpp b/ACE/examples/Service_Configurator/IPC-tests/client/local_stream_client_test.cpp
new file mode 100644
index 00000000000..390b14e19b8
--- /dev/null
+++ b/ACE/examples/Service_Configurator/IPC-tests/client/local_stream_client_test.cpp
@@ -0,0 +1,113 @@
+// $Id$
+
+// Tests out the UNIX domain IPC-SAP abstraction.
+
+#include "ace/OS_main.h"
+#include "ace/LSOCK_Connector.h"
+#include "ace/UNIX_Addr.h"
+#include "ace/Get_Opt.h"
+#include "ace/OS_NS_stdlib.h"
+#include "ace/OS_NS_unistd.h"
+#include "ace/OS_NS_fcntl.h"
+
+ACE_RCSID(client, local_stream_client_test, "$Id$")
+
+#if defined (ACE_HAS_MSG) && !defined (ACE_LACKS_UNIX_DOMAIN_SOCKETS)
+// Name of the program.
+static ACE_TCHAR *program_name;
+
+// Name of rendezvous point.
+static const ACE_TCHAR *rendezvous = ACE_TEXT ("/tmp/foo_stream");
+
+// Name of file to send.
+static const ACE_TCHAR *file_name = ACE_TEXT ("local_data");
+
+static void
+print_usage_and_die (void)
+{
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("usage: %s [-r rendezvous] [-f file]\n"),
+ program_name));
+ ACE_OS::exit (1);
+}
+
+void
+parse_args (int argc, ACE_TCHAR *argv[])
+{
+ program_name = argv[0];
+ ACE_Get_Opt get_opt (argc, argv, ACE_TEXT ("f:r:"));
+
+ for (int c; (c = get_opt ()) != -1; )
+ switch (c)
+ {
+ case 'f':
+ file_name = get_opt.opt_arg ();
+ break;
+ case 'r':
+ rendezvous = get_opt.opt_arg ();
+ break;
+ default:
+ print_usage_and_die ();
+ break;
+ }
+}
+
+int
+ACE_TMAIN (int argc, ACE_TCHAR *argv[])
+{
+ parse_args (argc, argv);
+
+ int fd;
+ char buf[BUFSIZ];
+ int n;
+
+ ACE_LSOCK_Stream sc;
+ ACE_LSOCK_Connector con;
+
+ if (con.connect (sc,
+ ACE_UNIX_Addr (rendezvous)) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("connect")),
+ -1);
+
+ if ((fd = ACE_OS::open (file_name,
+ O_RDONLY)) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("open")),
+ -1);
+
+ // Send the open file descriptor to the server!
+
+ if (sc.send_handle (fd) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("send_handle")),
+ -1);
+
+ if ((n = sc.recv_n (buf,
+ sizeof buf)) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("recv")),
+ -1);
+ else
+ ACE_OS::write (ACE_STDOUT, buf, n);
+
+ if (ACE_OS::close (fd) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("close")),
+ -1);
+
+ return 0;
+}
+#else
+int ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("your platform must support sendmsg/recvmsg to run this test\n")),
+ -1);
+}
+#endif /* ACE_HAS_MSG */
diff --git a/ACE/examples/Service_Configurator/IPC-tests/client/remote_data b/ACE/examples/Service_Configurator/IPC-tests/client/remote_data
new file mode 100644
index 00000000000..ae7e1fbb88e
--- /dev/null
+++ b/ACE/examples/Service_Configurator/IPC-tests/client/remote_data
@@ -0,0 +1,22 @@
+remoteremoteremoteremoteremoteremoteremoteremote
+remoteremoteremoteremoteremoteremoteremoteremote
+remoteremoteremoteremoteremoteremoteremoteremote
+remoteremoteremoteremoteremoteremoteremoteremote
+remoteremoteremoteremoteremoteremoteremoteremote
+remoteremoteremoteremoteremoteremoteremoteremote
+remoteremoteremoteremoteremoteremoteremoteremote
+remoteremoteremoteremoteremoteremoteremoteremote
+remoteremoteremoteremoteremoteremoteremoteremote
+remoteremoteremoteremoteremoteremoteremoteremote
+remoteremoteremoteremoteremoteremoteremoteremote
+remoteremoteremoteremoteremoteremoteremoteremote
+remoteremoteremoteremoteremoteremoteremoteremote
+remoteremoteremoteremoteremoteremoteremoteremote
+remoteremoteremoteremoteremoteremoteremoteremote
+remoteremoteremoteremoteremoteremoteremoteremote
+remoteremoteremoteremoteremoteremoteremoteremote
+remoteremoteremoteremoteremoteremoteremoteremote
+remoteremoteremoteremoteremoteremoteremoteremote
+remoteremoteremoteremoteremoteremoteremoteremote
+remoteremoteremoteremoteremoteremoteremoteremote
+remoteremoteremoteremoteremoteremoteremoteremote
diff --git a/ACE/examples/Service_Configurator/IPC-tests/client/remote_data1 b/ACE/examples/Service_Configurator/IPC-tests/client/remote_data1
new file mode 100644
index 00000000000..6faaee46729
--- /dev/null
+++ b/ACE/examples/Service_Configurator/IPC-tests/client/remote_data1
@@ -0,0 +1,22 @@
+remote1remote1remote1remote1remote1remote1remote1remote1
+remote1remote1remote1remote1remote1remote1remote1remote1
+remote1remote1remote1remote1remote1remote1remote1remote1
+remote1remote1remote1remote1remote1remote1remote1remote1
+remote1remote1remote1remote1remote1remote1remote1remote1
+remote1remote1remote1remote1remote1remote1remote1remote1
+remote1remote1remote1remote1remote1remote1remote1remote1
+remote1remote1remote1remote1remote1remote1remote1remote1
+remote1remote1remote1remote1remote1remote1remote1remote1
+remote1remote1remote1remote1remote1remote1remote1remote1
+remote1remote1remote1remote1remote1remote1remote1remote1
+remote1remote1remote1remote1remote1remote1remote1remote1
+remote1remote1remote1remote1remote1remote1remote1remote1
+remote1remote1remote1remote1remote1remote1remote1remote1
+remote1remote1remote1remote1remote1remote1remote1remote1
+remote1remote1remote1remote1remote1remote1remote1remote1
+remote1remote1remote1remote1remote1remote1remote1remote1
+remote1remote1remote1remote1remote1remote1remote1remote1
+remote1remote1remote1remote1remote1remote1remote1remote1
+remote1remote1remote1remote1remote1remote1remote1remote1
+remote1remote1remote1remote1remote1remote1remote1remote1
+remote1remote1remote1remote1remote1remote1remote1remote1
diff --git a/ACE/examples/Service_Configurator/IPC-tests/client/remote_data2 b/ACE/examples/Service_Configurator/IPC-tests/client/remote_data2
new file mode 100644
index 00000000000..ae6bf12d49f
--- /dev/null
+++ b/ACE/examples/Service_Configurator/IPC-tests/client/remote_data2
@@ -0,0 +1,22 @@
+remote2remote2remote2remote2remote2remote2remote2remote2
+remote2remote2remote2remote2remote2remote2remote2remote2
+remote2remote2remote2remote2remote2remote2remote2remote2
+remote2remote2remote2remote2remote2remote2remote2remote2
+remote2remote2remote2remote2remote2remote2remote2remote2
+remote2remote2remote2remote2remote2remote2remote2remote2
+remote2remote2remote2remote2remote2remote2remote2remote2
+remote2remote2remote2remote2remote2remote2remote2remote2
+remote2remote2remote2remote2remote2remote2remote2remote2
+remote2remote2remote2remote2remote2remote2remote2remote2
+remote2remote2remote2remote2remote2remote2remote2remote2
+remote2remote2remote2remote2remote2remote2remote2remote2
+remote2remote2remote2remote2remote2remote2remote2remote2
+remote2remote2remote2remote2remote2remote2remote2remote2
+remote2remote2remote2remote2remote2remote2remote2remote2
+remote2remote2remote2remote2remote2remote2remote2remote2
+remote2remote2remote2remote2remote2remote2remote2remote2
+remote2remote2remote2remote2remote2remote2remote2remote2
+remote2remote2remote2remote2remote2remote2remote2remote2
+remote2remote2remote2remote2remote2remote2remote2remote2
+remote2remote2remote2remote2remote2remote2remote2remote2
+remote2remote2remote2remote2remote2remote2remote2remote2
diff --git a/ACE/examples/Service_Configurator/IPC-tests/client/remote_data3 b/ACE/examples/Service_Configurator/IPC-tests/client/remote_data3
new file mode 100644
index 00000000000..7f2ec1aa81b
--- /dev/null
+++ b/ACE/examples/Service_Configurator/IPC-tests/client/remote_data3
@@ -0,0 +1,22 @@
+remote3remote3remote3remote3remote3remote3remote3remote3
+remote3remote3remote3remote3remote3remote3remote3remote3
+remote3remote3remote3remote3remote3remote3remote3remote3
+remote3remote3remote3remote3remote3remote3remote3remote3
+remote3remote3remote3remote3remote3remote3remote3remote3
+remote3remote3remote3remote3remote3remote3remote3remote3
+remote3remote3remote3remote3remote3remote3remote3remote3
+remote3remote3remote3remote3remote3remote3remote3remote3
+remote3remote3remote3remote3remote3remote3remote3remote3
+remote3remote3remote3remote3remote3remote3remote3remote3
+remote3remote3remote3remote3remote3remote3remote3remote3
+remote3remote3remote3remote3remote3remote3remote3remote3
+remote3remote3remote3remote3remote3remote3remote3remote3
+remote3remote3remote3remote3remote3remote3remote3remote3
+remote3remote3remote3remote3remote3remote3remote3remote3
+remote3remote3remote3remote3remote3remote3remote3remote3
+remote3remote3remote3remote3remote3remote3remote3remote3
+remote3remote3remote3remote3remote3remote3remote3remote3
+remote3remote3remote3remote3remote3remote3remote3remote3
+remote3remote3remote3remote3remote3remote3remote3remote3
+remote3remote3remote3remote3remote3remote3remote3remote3
+remote3remote3remote3remote3remote3remote3remote3remote3
diff --git a/ACE/examples/Service_Configurator/IPC-tests/client/remote_data4 b/ACE/examples/Service_Configurator/IPC-tests/client/remote_data4
new file mode 100644
index 00000000000..6c5a9633d56
--- /dev/null
+++ b/ACE/examples/Service_Configurator/IPC-tests/client/remote_data4
@@ -0,0 +1,22 @@
+remote4remote4remote4remote4remote4remote4remote4remote4
+remote4remote4remote4remote4remote4remote4remote4remote4
+remote4remote4remote4remote4remote4remote4remote4remote4
+remote4remote4remote4remote4remote4remote4remote4remote4
+remote4remote4remote4remote4remote4remote4remote4remote4
+remote4remote4remote4remote4remote4remote4remote4remote4
+remote4remote4remote4remote4remote4remote4remote4remote4
+remote4remote4remote4remote4remote4remote4remote4remote4
+remote4remote4remote4remote4remote4remote4remote4remote4
+remote4remote4remote4remote4remote4remote4remote4remote4
+remote4remote4remote4remote4remote4remote4remote4remote4
+remote4remote4remote4remote4remote4remote4remote4remote4
+remote4remote4remote4remote4remote4remote4remote4remote4
+remote4remote4remote4remote4remote4remote4remote4remote4
+remote4remote4remote4remote4remote4remote4remote4remote4
+remote4remote4remote4remote4remote4remote4remote4remote4
+remote4remote4remote4remote4remote4remote4remote4remote4
+remote4remote4remote4remote4remote4remote4remote4remote4
+remote4remote4remote4remote4remote4remote4remote4remote4
+remote4remote4remote4remote4remote4remote4remote4remote4
+remote4remote4remote4remote4remote4remote4remote4remote4
+remote4remote4remote4remote4remote4remote4remote4remote4
diff --git a/ACE/examples/Service_Configurator/IPC-tests/client/remote_dgram_client_test.cpp b/ACE/examples/Service_Configurator/IPC-tests/client/remote_dgram_client_test.cpp
new file mode 100644
index 00000000000..e5bec64d8c6
--- /dev/null
+++ b/ACE/examples/Service_Configurator/IPC-tests/client/remote_dgram_client_test.cpp
@@ -0,0 +1,92 @@
+// $Id$
+
+// Tests out the Internet domain IPC-SAP dgram abstraction.
+
+#include "ace/OS_main.h"
+#include "ace/OS_NS_stdlib.h"
+#include "ace/Mem_Map.h"
+#include "ace/SOCK_Dgram.h"
+#include "ace/INET_Addr.h"
+#include "ace/Get_Opt.h"
+#include "ace/Log_Msg.h"
+
+ACE_RCSID(client, remote_dgram_client_test, "$Id$")
+
+// Name of the program.
+static const ACE_TCHAR *program_name;
+
+// Port number to use.
+static u_short port_number = ACE_DEFAULT_SERVER_PORT;
+
+// Name of remote host.
+static const ACE_TCHAR *host_name = ACE_DEFAULT_SERVER_HOST;
+
+// Name of file to send.
+static const ACE_TCHAR *file_name = ACE_TEXT("./remote_data");
+
+static void print_usage_and_die (void)
+{
+ ACE_ERROR ((LM_ERROR,
+ "usage: %s [-p portnum] [-h host_name] [-f file]\n",
+ program_name));
+ ACE_OS::exit (1);
+}
+
+void
+parse_args (int argc, ACE_TCHAR *argv[])
+{
+ program_name = argv[0];
+
+ ACE_Get_Opt get_opt (argc, argv, ACE_TEXT("f:h:p:"));
+
+ for (int c; (c = get_opt ()) != -1; )
+ switch (c)
+ {
+ case 'f':
+ file_name = get_opt.opt_arg ();
+ break;
+ case 'h':
+ host_name = get_opt.opt_arg ();
+ break;
+ case 'p':
+ port_number = ACE_OS::atoi (get_opt.opt_arg ());
+ break;
+ default:
+ print_usage_and_die ();
+ break;
+ }
+}
+
+int
+ACE_TMAIN (int argc, ACE_TCHAR *argv[])
+{
+ parse_args (argc, argv);
+
+ ACE_SOCK_Dgram sd (ACE_Addr::sap_any);
+ void *cp = 0;
+ ACE_INET_Addr sa (port_number, host_name);
+
+ ACE_Mem_Map mmap (file_name);
+
+ if (mmap (cp) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%p\n",
+ "mmap"),
+ -1);
+
+ // Next, send the file's contents.
+
+ ssize_t cc = sd.send (cp, mmap.size (), sa);
+
+ if (cc == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%p\n",
+ "send"),
+ -1);
+ else if (cc != (ssize_t) mmap.size ())
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%p\n",
+ "Not all the contents of mmap file are sent."),
+ -1);
+ return 0;
+}
diff --git a/ACE/examples/Service_Configurator/IPC-tests/client/remote_service_directory_test.cpp b/ACE/examples/Service_Configurator/IPC-tests/client/remote_service_directory_test.cpp
new file mode 100644
index 00000000000..cee8ca1469f
--- /dev/null
+++ b/ACE/examples/Service_Configurator/IPC-tests/client/remote_service_directory_test.cpp
@@ -0,0 +1,111 @@
+// $Id$
+
+// Test program for the INET IPC-SAPs...
+
+#include "ace/OS_main.h"
+#include "ace/OS_NS_stdlib.h"
+#include "ace/OS_NS_unistd.h"
+#include "ace/OS_NS_string.h"
+#include "ace/SOCK_Connector.h"
+#include "ace/INET_Addr.h"
+#include "ace/Get_Opt.h"
+#include "ace/Log_Msg.h"
+
+ACE_RCSID(client, remote_service_directory_test, "$Id$")
+
+// Port number to use.
+static unsigned short port_number = ACE_DEFAULT_SERVICE_PORT;
+
+// Name of remote host.
+static const ACE_TCHAR *host_name = ACE_DEFAULT_SERVER_HOST;
+
+// Trigger a remote reconfiguration.
+static int remote_reconfigure = 0;
+
+static void
+print_usage_and_die (void)
+{
+ ACE_ERROR ((LM_ERROR,
+ "usage: %n [-p portnum] [-h host_name] [-r]\n"));
+ ACE_OS::exit (1);
+}
+
+void
+parse_args (int argc, ACE_TCHAR *argv[])
+{
+ ACE_Get_Opt get_opt (argc, argv, ACE_TEXT("p:h:r"));
+
+ for (int c; (c = get_opt ()) != -1; )
+ switch (c)
+ {
+ case 'h':
+ host_name = get_opt.opt_arg ();
+ break;
+ case 'p':
+ port_number = ACE_OS::atoi (get_opt.opt_arg ());
+ break;
+ case 'r':
+ remote_reconfigure = 1;
+ break;
+ default:
+ print_usage_and_die ();
+ break;
+ }
+}
+
+int
+ACE_TMAIN (int argc, ACE_TCHAR *argv[])
+{
+ ACE_LOG_MSG->open (argv[0]);
+
+ parse_args (argc, argv);
+ // Default is to ask the server for ``help.''
+ static char buf[BUFSIZ] = "help\n";
+ int n;
+ ACE_SOCK_Stream sc;
+ ACE_SOCK_Connector con;
+
+ if (con.connect (sc,
+ ACE_INET_Addr (port_number,
+ host_name)) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%p\n%a",
+ "connect",
+ 1),
+ -1);
+
+ if (remote_reconfigure)
+ // Remotely instruct the server to reconfigure itself.
+ ACE_OS::strcpy (buf, "reconfigure\n");
+
+ // Send the command.
+
+ if (sc.send_n (buf,
+ ACE_OS::strlen (buf) + 1) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%p\n%a",
+ "send",
+ 1), -1);
+
+ // Next, read the response.
+
+ while ((n = sc.recv (buf,
+ sizeof buf)) > 0)
+ if (ACE_OS::write (ACE_STDOUT,
+ buf,
+ n) != n)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%p\n%a",
+ "write",
+ 1),
+ -1);
+
+ if (sc.close () == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%p\n%a",
+ "close",
+ 1),
+ -1);
+
+ return 0;
+}
diff --git a/ACE/examples/Service_Configurator/IPC-tests/client/remote_stream_client_test.cpp b/ACE/examples/Service_Configurator/IPC-tests/client/remote_stream_client_test.cpp
new file mode 100644
index 00000000000..d7d4ef7346c
--- /dev/null
+++ b/ACE/examples/Service_Configurator/IPC-tests/client/remote_stream_client_test.cpp
@@ -0,0 +1,134 @@
+// $Id$
+
+// Test program for the INET IPC-SAPs...
+
+#include "ace/OS_main.h"
+#include "ace/OS_NS_stdlib.h"
+#include "ace/OS_NS_string.h"
+#include "ace/OS_NS_unistd.h"
+#include "ace/Mem_Map.h"
+#include "ace/SOCK_Connector.h"
+#include "ace/SOCK_CODgram.h"
+#include "ace/INET_Addr.h"
+#include "ace/Get_Opt.h"
+#include "ace/Log_Msg.h"
+
+ACE_RCSID(client, remote_stream_client_test, "$Id$")
+
+// Name of the program.
+static const ACE_TCHAR *program_name;
+
+// Port number to use.
+static u_short port_number = ACE_DEFAULT_SERVER_PORT;
+
+// Name of remote host.
+static const ACE_TCHAR *host_name = ACE_DEFAULT_SERVER_HOST;
+
+// Name of file to send.
+static const ACE_TCHAR *file_name = ACE_TEXT("./remote_data");
+
+static void
+print_usage_and_die (void)
+{
+ ACE_ERROR ((LM_ERROR,
+ "usage: %s [-p portnum] [-h host_name] [-f file]\n",
+ program_name));
+ ACE_OS::exit (1);
+}
+
+void
+parse_args (int argc, ACE_TCHAR *argv[])
+{
+ program_name = argv[0];
+ ACE_Get_Opt get_opt (argc, argv, ACE_TEXT("f:h:p:"));
+
+ for (int c; (c = get_opt ()) != -1; )
+ switch (c)
+ {
+ case 'f':
+ file_name = get_opt.opt_arg ();
+ break;
+ case 'h':
+ host_name = get_opt.opt_arg ();
+ break;
+ case 'p':
+ port_number = ACE_OS::atoi (get_opt.opt_arg ());
+ break;
+ default:
+ print_usage_and_die ();
+ break;
+ }
+}
+
+int
+ACE_TMAIN (int argc, ACE_TCHAR *argv[])
+{
+ parse_args (argc, argv);
+ ACE_INET_Addr sa (port_number, host_name);
+ void *cp = 0;
+ char buf[BUFSIZ];
+ int n;
+ ACE_SOCK_CODgram dc;
+
+ if (dc.open (sa, ACE_Addr::sap_any) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%p\n",
+ "open"),
+ -1);
+
+ // First send the name of the file as a datagram.
+
+ iovec iov[2];
+
+ iov[0].iov_base = (char *) "filename: ";
+ iov[0].iov_len = 11;
+ iov[1].iov_base = (char *) file_name;
+ iov[1].iov_len = ACE_OS::strlen (file_name);
+
+ if (dc.send (iov, 2) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%p\n",
+ "send"),
+ -1);
+
+ ACE_SOCK_Stream sc;
+ ACE_SOCK_Connector con;
+
+ if (con.connect (sc, sa) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%p\n",
+ "connect"),
+ -1);
+
+ ACE_Mem_Map mmap (file_name);
+
+ if (mmap (cp) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%p\n",
+ "mmap"),
+ -1);
+
+ // Next, send the file's contents.
+
+ if (sc.send_n (cp, mmap.size ()) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%p\n",
+ "send_urg"),
+ -1);
+
+ if (sc.close_writer () == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%p\n",
+ "close_writer"),
+ -1);
+
+ if ((n = sc.recv_n (buf, sizeof buf)) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%p\n",
+ "recv"),
+ -1);
+ else
+ ACE_OS::write (ACE_STDOUT, buf, n);
+
+ return 0;
+}
diff --git a/ACE/examples/Service_Configurator/IPC-tests/client/remote_thr_stream_client_test.cpp b/ACE/examples/Service_Configurator/IPC-tests/client/remote_thr_stream_client_test.cpp
new file mode 100644
index 00000000000..113c809069d
--- /dev/null
+++ b/ACE/examples/Service_Configurator/IPC-tests/client/remote_thr_stream_client_test.cpp
@@ -0,0 +1,122 @@
+// $Id$
+
+// Test program for the INET ACE_TLI-SAPs...
+
+#include "ace/OS_main.h"
+#include "ace/OS_NS_stdlib.h"
+#include "ace/OS_NS_unistd.h"
+#include "ace/Mem_Map.h"
+#include "ace/TLI_Connector.h"
+#include "ace/INET_Addr.h"
+#include "ace/Get_Opt.h"
+#include "ace/Log_Msg.h"
+
+ACE_RCSID(client, remote_thr_stream_client_test, "$Id$")
+
+#if defined (ACE_HAS_TLI)
+
+// Name of the program.
+static const ACE_TCHAR *program_name;
+
+// Port number to use.
+static u_short port_number = ACE_DEFAULT_THR_PORT;
+
+// Name of remote host.
+static const ACE_TCHAR *host_name = ACE_DEFAULT_SERVER_HOST;
+
+// Name of file to send.
+static const ACE_TCHAR *file_name = ACE_TEXT ("./remote_data");
+
+static void print_usage_and_die (void)
+{
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("usage: %s [-p portnum] [-h host_name] [-f file]\n"),
+ program_name));
+ ACE_OS::exit (1);
+}
+
+void
+parse_args (int argc, ACE_TCHAR *argv[])
+{
+ program_name = argv[0];
+ ACE_Get_Opt get_opt (argc, argv, ACE_TEXT ("f:h:p:"));
+
+ for (int c; (c = get_opt ()) != -1; )
+ switch (c)
+ {
+ case 'f':
+ file_name = get_opt.opt_arg ();
+ break;
+ case 'h':
+ host_name = get_opt.opt_arg ();
+ break;
+ case 'p':
+ port_number = ACE_OS::atoi (get_opt.opt_arg ());
+ break;
+ default:
+ print_usage_and_die ();
+ break;
+ }
+}
+
+int
+ACE_TMAIN (int argc, ACE_TCHAR *argv[])
+{
+ parse_args (argc, argv);
+ void *cp;
+ char buf[BUFSIZ];
+ ACE_TLI_Stream sc;
+ ACE_TLI_Connector con;
+
+ if (con.connect (sc,
+ ACE_INET_Addr (port_number,
+ host_name)) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("open")),
+ -1);
+
+ ACE_Mem_Map mmap (file_name, PROT_READ);
+
+ if (mmap (cp) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("mmap")), -1);
+
+ // Next, send the file's contents.
+
+ if (sc.send_n (cp, mmap.size ()) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("send_n")),
+ -1);
+
+ if (sc.sndrel () == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("close_writer")),
+ -1);
+
+ for (int n; (n = sc.recv (buf, sizeof buf)) > 0; )
+ if (ACE_OS::write (ACE_STDOUT, buf, n) != n)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("write")),
+ -1);
+
+ if (sc.close () == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("close")),
+ -1);
+ return 0;
+}
+#else
+int
+ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("you must have TLI to run this test\n")),
+ 1);
+}
+#endif /* ACE_HAS_TLI */
diff --git a/ACE/examples/Service_Configurator/IPC-tests/server/.cvsignore b/ACE/examples/Service_Configurator/IPC-tests/server/.cvsignore
new file mode 100644
index 00000000000..74fdfbc7f93
--- /dev/null
+++ b/ACE/examples/Service_Configurator/IPC-tests/server/.cvsignore
@@ -0,0 +1 @@
+server_test
diff --git a/ACE/examples/Service_Configurator/IPC-tests/server/Handle_Broadcast.cpp b/ACE/examples/Service_Configurator/IPC-tests/server/Handle_Broadcast.cpp
new file mode 100644
index 00000000000..30db7825244
--- /dev/null
+++ b/ACE/examples/Service_Configurator/IPC-tests/server/Handle_Broadcast.cpp
@@ -0,0 +1,38 @@
+// $Id$
+
+#include "Handle_Broadcast.h"
+
+ACE_RCSID(server, Handle_Broadcast, "$Id$")
+
+#if defined (SunOS4)
+extern "C"
+{
+ int init (void);
+ int fini (void);
+ void __sti__Handle_Broadcast_C_init_();
+ void __std__Handle_Broadcast_C_init_();
+}
+
+int
+init (void)
+{
+ __sti__Handle_Broadcast_C_init_();
+ return 0;
+}
+
+int
+fini (void)
+{
+ __std__Handle_Broadcast_C_init_();
+ return 0;
+}
+#endif /* SunOS4 */
+
+unsigned short Handle_Broadcast::DEFAULT_PORT = ACE_DEFAULT_BROADCAST_PORT;
+
+#if !defined (__ACE_INLINE__)
+#include "Handle_Broadcast.i"
+#endif /* __ACE_INLINE__ */
+
+Handle_Broadcast remote_broadcast;
+ACE_Service_Object_Type rb (&remote_broadcast, ACE_TEXT("Remote_Brdcast"));
diff --git a/ACE/examples/Service_Configurator/IPC-tests/server/Handle_Broadcast.h b/ACE/examples/Service_Configurator/IPC-tests/server/Handle_Broadcast.h
new file mode 100644
index 00000000000..8b382f9fd73
--- /dev/null
+++ b/ACE/examples/Service_Configurator/IPC-tests/server/Handle_Broadcast.h
@@ -0,0 +1,50 @@
+// -*- C++ -*-
+//
+// $Id$
+
+/* Handles INET broadcast datagram messages from remote hosts on the local subnet. */
+
+#ifndef _HANDLE_BROADCAST_H
+#define _HANDLE_BROADCAST_H
+
+#include "ace/Service_Config.h"
+#include "ace/Reactor.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/Service_Types.h"
+#include "ace/INET_Addr.h"
+#include "ace/SOCK_Dgram.h"
+#include "ace/Log_Msg.h"
+#include "ace/svc_export.h"
+
+class ACE_Svc_Export Handle_Broadcast : public ACE_Service_Object, public ACE_SOCK_Dgram
+{
+public:
+ Handle_Broadcast (void);
+ ~Handle_Broadcast (void);
+ virtual int init (int argc, ACE_TCHAR *argv[]);
+ virtual int info (ACE_TCHAR **, size_t) const;
+ virtual int fini (void);
+
+private:
+ int open (const ACE_INET_Addr &r, int async = 0);
+ virtual ACE_HANDLE get_handle (void) const;
+ virtual int handle_input (ACE_HANDLE fd);
+ virtual int handle_close (ACE_HANDLE fd, ACE_Reactor_Mask);
+
+ static unsigned short DEFAULT_PORT;
+};
+
+extern ACE_Service_Object_Type rb;
+
+#if defined (__ACE_INLINE__)
+#define ACE_INLINE inline
+#include "Handle_Broadcast.i"
+#else
+#define ACE_INLINE
+#endif /* __ACE_INLINE__ */
+
+#endif /* _HANDLE_BROADCAST_H */
diff --git a/ACE/examples/Service_Configurator/IPC-tests/server/Handle_Broadcast.i b/ACE/examples/Service_Configurator/IPC-tests/server/Handle_Broadcast.i
new file mode 100644
index 00000000000..ce7f42617e7
--- /dev/null
+++ b/ACE/examples/Service_Configurator/IPC-tests/server/Handle_Broadcast.i
@@ -0,0 +1,116 @@
+/* -*- C++ -*- */
+// $Id$
+
+#include "ace/Get_Opt.h"
+#include "ace/OS_NS_stdio.h"
+#include "ace/OS_NS_string.h"
+#include "ace/OS_NS_unistd.h"
+
+ACE_INLINE
+Handle_Broadcast::~Handle_Broadcast (void)
+{
+}
+
+ACE_INLINE
+Handle_Broadcast::Handle_Broadcast (void)
+{
+}
+
+ACE_INLINE int
+Handle_Broadcast::open (const ACE_INET_Addr &r, int async)
+{
+ if (this->ACE_SOCK_Dgram::open (r) == -1)
+ return -1;
+ else if (async && ACE_SOCK_Dgram::enable (ACE_SIGIO) == -1)
+ return -1;
+ else
+ return 0;
+}
+
+ACE_INLINE int
+Handle_Broadcast::info (ACE_TCHAR **strp, size_t length) const
+{
+ ACE_TCHAR buf[BUFSIZ];
+ ACE_INET_Addr sa;
+
+ if (this->get_local_addr (sa) == -1)
+ return -1;
+
+ ACE_OS::sprintf (buf, ACE_TEXT("%d/"), sa.get_port_number ());
+ ACE_OS::strcat (buf, ACE_TEXT("udp # tests broadcasting\n"));
+
+ if (*strp == 0 && (*strp = ACE_OS::strdup (buf)) == 0)
+ return -1;
+ else
+ ACE_OS::strncpy (*strp, buf, length);
+ return ACE_OS::strlen (buf);
+}
+
+ACE_INLINE int
+Handle_Broadcast::init (int argc, ACE_TCHAR *argv[])
+{
+ ACE_INET_Addr sba (Handle_Broadcast::DEFAULT_PORT);
+ ACE_Get_Opt get_opt (argc, argv, ACE_TEXT("p:"), 0);
+
+ for (int c; (c = get_opt ()) != -1; )
+ switch (c)
+ {
+ case 'p':
+ sba.set (ACE_OS::atoi (get_opt.opt_arg ()));
+ break;
+ default:
+ break;
+ }
+
+ if (this->open (sba) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("%p\n"), ACE_TEXT ("open")), -1);
+ else if (ACE_Reactor::instance ()->register_handler
+ (this, ACE_Event_Handler::ACCEPT_MASK) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("%p\n"),
+ ACE_TEXT ("registering service with ACE_Reactor")), -1);
+ return 0;
+}
+
+ACE_INLINE int
+Handle_Broadcast::fini (void)
+{
+ return ACE_Reactor::instance ()->remove_handler
+ (this, ACE_Event_Handler::ACCEPT_MASK);
+}
+
+ACE_INLINE ACE_HANDLE
+Handle_Broadcast::get_handle (void) const
+{
+ return this->ACE_SOCK_Dgram::get_handle ();
+}
+
+ACE_INLINE int
+Handle_Broadcast::handle_input (ACE_HANDLE)
+{
+ ACE_INET_Addr sa;
+ char buf[8 * 1024]; /* 8 k buffer */
+ ssize_t n = this->recv (buf, sizeof buf, sa);
+
+ if (n== -1)
+ return -1;
+ else
+ ACE_DEBUG ((LM_INFO,
+ ACE_TEXT ("received broadcast datagram from host %C\n"),
+ sa.get_host_name ()));
+
+ ACE_OS::puts (ACE_TEXT ("----------------------------------------"));
+ ACE_OS::write (ACE_STDOUT, buf, n);
+
+ if (buf[n - 1] != '\n')
+ putchar ('\n');
+
+ ACE_OS::puts (ACE_TEXT ("----------------------------------------"));
+
+ return 0;
+}
+
+ACE_INLINE int
+Handle_Broadcast::handle_close (ACE_HANDLE, ACE_Reactor_Mask)
+{
+ return this->ACE_SOCK_Dgram::close ();
+}
diff --git a/ACE/examples/Service_Configurator/IPC-tests/server/Handle_L_CODgram.cpp b/ACE/examples/Service_Configurator/IPC-tests/server/Handle_L_CODgram.cpp
new file mode 100644
index 00000000000..6fe631fdb41
--- /dev/null
+++ b/ACE/examples/Service_Configurator/IPC-tests/server/Handle_L_CODgram.cpp
@@ -0,0 +1,19 @@
+// $Id$
+
+#include "Handle_L_CODgram.h"
+
+#if !defined (ACE_LACKS_UNIX_DOMAIN_SOCKETS)
+
+ACE_RCSID(server, Handle_L_CODgram, "$Id$")
+
+const ACE_TCHAR *Handle_L_CODgram::DEFAULT_RENDEZVOUS =
+ ACE_TEXT ("/tmp/foo_codgram");
+
+#if !defined (__ACE_INLINE__)
+#include "Handle_L_CODgram.i"
+#endif /* __ACE_INLINE__ */
+
+Handle_L_CODgram local_codgram;
+ACE_Service_Object_Type lc (&local_codgram, ACE_TEXT ("Local_CODgram"));
+
+#endif /* ACE_LACKS_UNIX_DOMAIN_SOCKETS */
diff --git a/ACE/examples/Service_Configurator/IPC-tests/server/Handle_L_CODgram.h b/ACE/examples/Service_Configurator/IPC-tests/server/Handle_L_CODgram.h
new file mode 100644
index 00000000000..852c0557cda
--- /dev/null
+++ b/ACE/examples/Service_Configurator/IPC-tests/server/Handle_L_CODgram.h
@@ -0,0 +1,51 @@
+/* -*- C++ -*- */
+// $Id$
+
+// Handles UNIX datagram messages from local host.
+
+#ifndef _HANDLE_L_CODGRAM_H
+#define _HANDLE_L_CODGRAM_H
+
+#include "ace/Service_Config.h"
+#include "ace/Reactor.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/Service_Types.h"
+#include "ace/LSOCK_CODgram.h"
+#include "ace/UNIX_Addr.h"
+#include "ace/svc_export.h"
+
+#if !defined (ACE_LACKS_UNIX_DOMAIN_SOCKETS)
+
+class ACE_Svc_Export Handle_L_CODgram : public ACE_Service_Object, public ACE_LSOCK_CODgram
+{
+public:
+ Handle_L_CODgram (void);
+ virtual int init (int argc, ACE_TCHAR *argv[]);
+ virtual int info (ACE_TCHAR **, size_t) const;
+ virtual int fini (void);
+
+public:
+ int open (const ACE_UNIX_Addr &suad, int async = 0);
+ virtual ACE_HANDLE get_handle (void) const;
+ virtual int handle_input (ACE_HANDLE);
+ virtual int handle_close (ACE_HANDLE, ACE_Reactor_Mask);
+
+ ACE_TCHAR rendezvous[MAXPATHLEN + 1];
+ static const ACE_TCHAR *DEFAULT_RENDEZVOUS;
+};
+
+extern ACE_Service_Object_Type lc;
+
+#if defined (__ACE_INLINE__)
+#define ACE_INLINE inline
+#include "Handle_L_CODgram.i"
+#else
+#define ACE_INLINE
+#endif /* __ACE_INLINE__ */
+
+#endif /* ACE_LACKS_UNIX_DOMAIN_SOCKETS */
+#endif /* _HANDLE_L_CODGRAM_H */
diff --git a/ACE/examples/Service_Configurator/IPC-tests/server/Handle_L_CODgram.i b/ACE/examples/Service_Configurator/IPC-tests/server/Handle_L_CODgram.i
new file mode 100644
index 00000000000..a77d75e1fa8
--- /dev/null
+++ b/ACE/examples/Service_Configurator/IPC-tests/server/Handle_L_CODgram.i
@@ -0,0 +1,123 @@
+/* -*- C++ -*- */
+// $Id$
+
+#include "ace/Get_Opt.h"
+#include "ace/OS_NS_stdio.h"
+#include "ace/OS_NS_string.h"
+#include "ace/OS_NS_unistd.h"
+
+ACE_INLINE
+Handle_L_CODgram::Handle_L_CODgram (void)
+{
+}
+
+ACE_INLINE int
+Handle_L_CODgram::open (const ACE_UNIX_Addr &suad, int async)
+{
+ if (this->ACE_LSOCK_CODgram::open (ACE_Addr::sap_any, suad) == -1)
+ return -1;
+ else if (async && this->ACE_LSOCK_CODgram::enable (ACE_SIGIO) == -1)
+ return -1;
+ else
+ return 0;
+}
+
+ACE_INLINE int
+Handle_L_CODgram::info (ACE_TCHAR **strp, size_t length) const
+{
+ ACE_TCHAR buf[BUFSIZ];
+ ACE_UNIX_Addr sa;
+
+ if (ACE_LSOCK_CODgram::get_local_addr (sa) == -1)
+ return -1;
+
+ ACE_OS::strcpy (buf, ACE_TEXT_CHAR_TO_TCHAR (sa.get_path_name ()));
+ ACE_OS::strcat (buf, ACE_TEXT (" # tests local connected datagram\n"));
+
+ if (*strp == 0 && (*strp = ACE_OS::strdup (buf)) == 0)
+ return -1;
+ else
+ ACE_OS::strncpy (*strp, buf, length);
+ return ACE_OS::strlen (buf);
+}
+
+ACE_INLINE int
+Handle_L_CODgram::init (int argc, ACE_TCHAR *argv[])
+{
+ ACE_UNIX_Addr sucd;
+ ACE_Get_Opt get_opt (argc, argv, ACE_TEXT ("r:"), 0);
+ const ACE_TCHAR *r = Handle_L_CODgram::DEFAULT_RENDEZVOUS;
+
+ for (int c; (c = get_opt ()) != -1; )
+ switch (c)
+ {
+ case 'r':
+ r = get_opt.opt_arg ();
+ break;
+ default:
+ break;
+ }
+
+ ACE_OS::strncpy (this->rendezvous, r, MAXPATHLEN);
+ ACE_OS::unlink (this->rendezvous);
+ sucd.set (this->rendezvous);
+ if (this->open (sucd) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("%p\n"), ACE_TEXT ("open")), -1);
+ else if (ACE_Reactor::instance ()->register_handler
+ (this, ACE_Event_Handler::ACCEPT_MASK) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("%p\n"),
+ ACE_TEXT ("registering service with ACE_Reactor")),
+ -1);
+ return 0;
+}
+
+ACE_INLINE int
+Handle_L_CODgram::fini(void)
+{
+ return ACE_Reactor::instance ()->remove_handler
+ (this, ACE_Event_Handler::ACCEPT_MASK);
+}
+
+ACE_INLINE ACE_HANDLE
+Handle_L_CODgram::get_handle (void) const
+{
+ return ACE_LSOCK_CODgram::get_handle ();
+}
+
+ACE_INLINE int
+Handle_L_CODgram::handle_input (ACE_HANDLE)
+{
+ ACE_HANDLE handle = ACE_INVALID_HANDLE;
+ char buf[BUFSIZ];
+
+ if (this->recv_handle (handle) == -1)
+ return -1;
+ else
+ ACE_DEBUG ((LM_INFO, ACE_TEXT ("received handle (%d)\n"), handle));
+
+ ACE_OS::puts ("----------------------------------------");
+
+ for (;;)
+ {
+ ssize_t n = ACE_OS::read (handle, buf, sizeof buf);
+
+ if (n <= 0)
+ break;
+
+ ACE_OS::write (ACE_STDOUT, buf, n);
+ }
+
+ ACE_OS::puts ("----------------------------------------");
+
+ if (ACE_OS::close (handle) == -1)
+ return -1;
+
+ return 0;
+}
+
+ACE_INLINE int
+Handle_L_CODgram::handle_close (ACE_HANDLE, ACE_Reactor_Mask)
+{
+ this->ACE_LSOCK_CODgram::close ();
+ return ACE_OS::unlink (this->rendezvous);
+}
diff --git a/ACE/examples/Service_Configurator/IPC-tests/server/Handle_L_Dgram.cpp b/ACE/examples/Service_Configurator/IPC-tests/server/Handle_L_Dgram.cpp
new file mode 100644
index 00000000000..c502da057f7
--- /dev/null
+++ b/ACE/examples/Service_Configurator/IPC-tests/server/Handle_L_Dgram.cpp
@@ -0,0 +1,18 @@
+// $Id$
+
+#include "Handle_L_Dgram.h"
+
+ACE_RCSID(server, Handle_L_Dgram, "$Id$")
+
+#if !defined (ACE_LACKS_UNIX_DOMAIN_SOCKETS)
+
+const ACE_TCHAR *Handle_L_Dgram::DEFAULT_RENDEZVOUS =
+ ACE_TEXT ("/tmp/foo_dgram");
+
+#if !defined (__ACE_INLINE__)
+#include "Handle_L_Dgram.i"
+#endif /* __ACE_INLINE__ */
+
+Handle_L_Dgram local_dgram;
+ACE_Service_Object_Type ld (&local_dgram, ACE_TEXT ("Local_Dgram"));
+#endif /* ACE_LACKS_UNIX_DOMAIN_SOCKETS */
diff --git a/ACE/examples/Service_Configurator/IPC-tests/server/Handle_L_Dgram.h b/ACE/examples/Service_Configurator/IPC-tests/server/Handle_L_Dgram.h
new file mode 100644
index 00000000000..ac1eac69117
--- /dev/null
+++ b/ACE/examples/Service_Configurator/IPC-tests/server/Handle_L_Dgram.h
@@ -0,0 +1,51 @@
+// -*- C++ -*-
+// $Id$
+
+// Handles UNIX datagram messages from local host.
+
+#ifndef _HANDLE_L_DGRAM_H
+#define _HANDLE_L_DGRAM_H
+
+#include "ace/Service_Config.h"
+#include "ace/Reactor.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/Service_Types.h"
+#include "ace/LSOCK_Dgram.h"
+#include "ace/UNIX_Addr.h"
+#include "ace/svc_export.h"
+
+#if !defined (ACE_LACKS_UNIX_DOMAIN_SOCKETS)
+
+class ACE_Svc_Export Handle_L_Dgram : public ACE_Service_Object, public ACE_LSOCK_Dgram
+{
+public:
+ Handle_L_Dgram (void);
+ virtual int init (int argc, ACE_TCHAR *argv[]);
+ virtual int info (ACE_TCHAR **, size_t) const;
+ virtual int fini (void);
+
+private:
+ int open (const ACE_UNIX_Addr &suad, int async = 0);
+ virtual int get_handle (void) const;
+ virtual int handle_input (int fd);
+ virtual int handle_close (int fd, ACE_Reactor_Mask);
+
+ ACE_TCHAR rendezvous[MAXPATHLEN + 1];
+ static const ACE_TCHAR *DEFAULT_RENDEZVOUS;
+};
+
+extern ACE_Service_Object_Type ld;
+
+#if defined (__ACE_INLINE__)
+#define ACE_INLINE inline
+#include "Handle_L_Dgram.i"
+#else
+#define ACE_INLINE
+#endif /* __ACE_INLINE__ */
+
+#endif /* ACE_LACKS_UNIX_DOMAIN_SOCKETS */
+#endif /* _HANDLE_L_DGRAM_H */
diff --git a/ACE/examples/Service_Configurator/IPC-tests/server/Handle_L_Dgram.i b/ACE/examples/Service_Configurator/IPC-tests/server/Handle_L_Dgram.i
new file mode 100644
index 00000000000..3b2ab29331f
--- /dev/null
+++ b/ACE/examples/Service_Configurator/IPC-tests/server/Handle_L_Dgram.i
@@ -0,0 +1,116 @@
+/* -*- C++ -*- */
+// $Id$
+
+#include "ace/Get_Opt.h"
+#include "ace/OS_NS_stdio.h"
+#include "ace/OS_NS_string.h"
+#include "ace/OS_NS_unistd.h"
+
+ACE_INLINE
+Handle_L_Dgram::Handle_L_Dgram (void)
+{
+}
+
+ACE_INLINE int
+Handle_L_Dgram::open (const ACE_UNIX_Addr &suad, int async)
+{
+ if (this->ACE_LSOCK_Dgram::open (suad) == -1)
+ return -1;
+ else if (async && this->ACE_LSOCK_Dgram::enable (ACE_SIGIO) == -1)
+ return -1;
+ else
+ return 0;
+}
+
+ACE_INLINE int
+Handle_L_Dgram::info (ACE_TCHAR **strp, size_t length) const
+{
+ ACE_TCHAR buf[BUFSIZ];
+ ACE_UNIX_Addr sa;
+
+ if (this->ACE_LSOCK_Dgram::get_local_addr (sa) == -1)
+ return -1;
+
+ ACE_OS::strcpy (buf, ACE_TEXT_CHAR_TO_TCHAR (sa.get_path_name ()));
+ ACE_OS::strcat (buf, ACE_TEXT (" # tests local datagram\n"));
+
+ if (*strp == 0 && (*strp = ACE_OS::strdup (buf)) == 0)
+ return -1;
+ else
+ ACE_OS::strncpy (*strp, buf, length);
+ return ACE_OS::strlen (buf);
+}
+
+ACE_INLINE int
+Handle_L_Dgram::init (int argc, ACE_TCHAR *argv[])
+{
+ ACE_UNIX_Addr sudg;
+ ACE_Get_Opt get_opt (argc, argv, ACE_TEXT ("r:"), 0);
+ const ACE_TCHAR *r = Handle_L_Dgram::DEFAULT_RENDEZVOUS;
+
+ for (int c; (c = get_opt ()) != -1; )
+ switch (c)
+ {
+ case 'r':
+ r = get_opt.opt_arg ();
+ break;
+ default:
+ break;
+ }
+
+ ACE_OS::strncpy (this->rendezvous, r, MAXPATHLEN);
+ ACE_OS::unlink (this->rendezvous);
+ sudg.set (this->rendezvous);
+ if (this->open (sudg) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("%p\n"), ACE_TEXT ("open")), -1);
+ else if (ACE_Reactor::instance ()->register_handler (this,
+ ACE_Event_Handler::ACCEPT_MASK) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("registering service with ACE_Reactor")),
+ -1);
+ return 0;
+}
+
+ACE_INLINE int
+Handle_L_Dgram::fini (void)
+{
+ return ACE_Reactor::instance ()->remove_handler (this, ACE_Event_Handler::ACCEPT_MASK);
+}
+
+ACE_INLINE int
+Handle_L_Dgram::get_handle (void) const
+{
+ return this->ACE_LSOCK_Dgram::get_handle ();
+}
+
+ACE_INLINE int
+Handle_L_Dgram::handle_input (int)
+{
+ ACE_UNIX_Addr sa;
+ char buf[8 * 1024]; /* 8 k buffer */
+ int n;
+
+ if ((n = this->recv (buf, sizeof buf, sa)) == -1)
+ return -1;
+ else
+ ACE_DEBUG ((LM_INFO, ACE_TEXT ("received datagram from %s\n"),
+ sa.get_path_name ()));
+
+ ACE_OS::puts ("----------------------------------------");
+ ACE_OS::write (ACE_STDOUT, buf, n);
+
+ if (buf[n - 1] != '\n')
+ putchar ('\n');
+
+ ACE_OS::puts ("----------------------------------------");
+
+ return 0;
+}
+
+ACE_INLINE int
+Handle_L_Dgram::handle_close (int, ACE_Reactor_Mask)
+{
+ this->ACE_LSOCK_Dgram::close ();
+ return ACE_OS::unlink (this->rendezvous);
+}
diff --git a/ACE/examples/Service_Configurator/IPC-tests/server/Handle_L_FIFO.cpp b/ACE/examples/Service_Configurator/IPC-tests/server/Handle_L_FIFO.cpp
new file mode 100644
index 00000000000..609f7b3c24f
--- /dev/null
+++ b/ACE/examples/Service_Configurator/IPC-tests/server/Handle_L_FIFO.cpp
@@ -0,0 +1,38 @@
+// $Id$
+
+#include "Handle_L_FIFO.h"
+
+ACE_RCSID(server, Handle_L_FIFO, "$Id$")
+
+#if defined (SunOS4)
+extern "C"
+{
+ int init (void);
+ int fini (void);
+ void __sti__Handle_L_FIFO_C_init_();
+ void __std__Handle_L_FIFO_C_init_();
+}
+
+int
+init (void)
+{
+ __sti__Handle_L_FIFO_C_init_();
+ return 0;
+}
+
+int
+fini (void)
+{
+ __std__Handle_L_FIFO_C_init_();
+ return 0;
+}
+#endif /* SunOS4 */
+
+const ACE_TCHAR *Handle_L_FIFO::DEFAULT_RENDEZVOUS = ACE_TEXT("/tmp/foo_fifo");
+
+#if !defined (__ACE_INLINE__)
+#include "Handle_L_FIFO.i"
+#endif /* __ACE_INLINE__ */
+
+Handle_L_FIFO local_fifo;
+ACE_Service_Object_Type lf (&local_fifo, ACE_TEXT("Local_FIFO"));
diff --git a/ACE/examples/Service_Configurator/IPC-tests/server/Handle_L_FIFO.h b/ACE/examples/Service_Configurator/IPC-tests/server/Handle_L_FIFO.h
new file mode 100644
index 00000000000..4375b2d105c
--- /dev/null
+++ b/ACE/examples/Service_Configurator/IPC-tests/server/Handle_L_FIFO.h
@@ -0,0 +1,49 @@
+// -*- C++ -*-
+//
+// $Id$
+
+/* Handle connections from local UNIX ACE_FIFO */
+/* Read from a well known ACE_FIFO and write to stdout. */
+
+#ifndef _HANDLE_L_FIFO_H
+#define _HANDLE_L_FIFO_H
+
+#include "ace/Service_Config.h"
+#include "ace/Reactor.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/Service_Types.h"
+#include "ace/FIFO_Recv_Msg.h"
+#include "ace/Log_Msg.h"
+#include "ace/svc_export.h"
+
+class ACE_Svc_Export Handle_L_FIFO : public ACE_Service_Object, public ACE_FIFO_Recv_Msg
+{
+public:
+ Handle_L_FIFO (void);
+ virtual int init (int argc, ACE_TCHAR *argv[]);
+ virtual int info (ACE_TCHAR **, size_t) const;
+ virtual int fini (void);
+
+private:
+ int open (const ACE_TCHAR *rendezvous_fifo);
+ virtual ACE_HANDLE get_handle (void) const;
+ virtual int handle_input (ACE_HANDLE fd);
+ virtual int handle_close (ACE_HANDLE fd, ACE_Reactor_Mask);
+
+ static const ACE_TCHAR *DEFAULT_RENDEZVOUS;
+};
+
+extern ACE_Service_Object_Type lf;
+
+#if defined (__ACE_INLINE__)
+#define ACE_INLINE inline
+#include "Handle_L_FIFO.i"
+#else
+#define ACE_INLINE
+#endif /* __ACE_INLINE__ */
+
+#endif /* _HANDLE_L_FIFO_H */
diff --git a/ACE/examples/Service_Configurator/IPC-tests/server/Handle_L_FIFO.i b/ACE/examples/Service_Configurator/IPC-tests/server/Handle_L_FIFO.i
new file mode 100644
index 00000000000..f6cd0cda734
--- /dev/null
+++ b/ACE/examples/Service_Configurator/IPC-tests/server/Handle_L_FIFO.i
@@ -0,0 +1,101 @@
+/* -*- C++ -*- */
+// $Id$
+
+#include "ace/Get_Opt.h"
+#include "ace/OS_NS_stdio.h"
+#include "ace/OS_NS_string.h"
+#include "ace/OS_NS_stropts.h"
+#include "ace/OS_NS_unistd.h"
+
+ACE_INLINE
+Handle_L_FIFO::Handle_L_FIFO (void)
+{
+}
+
+ACE_INLINE int
+Handle_L_FIFO::open (const ACE_TCHAR *rendezvous_fifo)
+{
+ if (this->ACE_FIFO_Recv_Msg::open (rendezvous_fifo) == -1)
+ return -1;
+ else
+ return 0;
+}
+
+ACE_INLINE int
+Handle_L_FIFO::info (ACE_TCHAR **strp, size_t length) const
+{
+ ACE_TCHAR buf[BUFSIZ];
+ const ACE_TCHAR *rendezvous_fifo;
+
+ this->get_local_addr (rendezvous_fifo);
+
+ ACE_OS::strcpy (buf, rendezvous_fifo);
+ ACE_OS::strcat (buf, ACE_TEXT(" # tests local ACE_FIFO\n"));
+
+ if (*strp == 0 && (*strp = ACE_OS::strdup (buf)) == 0)
+ return -1;
+ else
+ ACE_OS::strncpy (*strp, buf, length);
+ return ACE_OS::strlen (buf);
+}
+
+ACE_INLINE int
+Handle_L_FIFO::init (int argc, ACE_TCHAR *argv[])
+{
+ const ACE_TCHAR *rendezvous_fifo = Handle_L_FIFO::DEFAULT_RENDEZVOUS;
+ ACE_Get_Opt get_opt (argc, argv, ACE_TEXT("r:"), 0);
+
+ for (int c; (c = get_opt ()) != -1; )
+ switch (c)
+ {
+ case 'r':
+ rendezvous_fifo = get_opt.opt_arg ();
+ break;
+ default:
+ break;
+ }
+
+ ACE_OS::unlink (rendezvous_fifo);
+ if (this->open (rendezvous_fifo) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("%p\n"), ACE_TEXT ("open")), -1);
+ else if (ACE_Reactor::instance ()->register_handler
+ (this, ACE_Event_Handler::READ_MASK) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("%p\n"),
+ ACE_TEXT ("registering service with ACE_Reactor")),
+ -1);
+ return 0;
+}
+
+ACE_INLINE int
+Handle_L_FIFO::fini (void)
+{
+ return ACE_Reactor::instance ()->remove_handler
+ (this, ACE_Event_Handler::ACCEPT_MASK);
+}
+
+ACE_INLINE ACE_HANDLE
+Handle_L_FIFO::get_handle (void) const
+{
+ return this->ACE_FIFO::get_handle ();
+}
+
+ACE_INLINE int
+Handle_L_FIFO::handle_input (ACE_HANDLE)
+{
+ char buf[PIPE_BUF];
+ ACE_Str_Buf msg (buf, 0, sizeof buf);
+
+ /* Accept communication requests */
+ if (this->recv (msg) == -1)
+ return -1;
+ else
+
+ ACE_OS::write (ACE_STDOUT, (const char *) msg.buf, (int) msg.len);
+ return 0;
+}
+
+ACE_INLINE int
+Handle_L_FIFO::handle_close (ACE_HANDLE, ACE_Reactor_Mask)
+{
+ return this->ACE_FIFO::remove ();
+}
diff --git a/ACE/examples/Service_Configurator/IPC-tests/server/Handle_L_Pipe.cpp b/ACE/examples/Service_Configurator/IPC-tests/server/Handle_L_Pipe.cpp
new file mode 100644
index 00000000000..a4508266363
--- /dev/null
+++ b/ACE/examples/Service_Configurator/IPC-tests/server/Handle_L_Pipe.cpp
@@ -0,0 +1,66 @@
+// $Id$
+
+#include "Handle_L_Pipe.h"
+#include "ace/OS_NS_ctype.h"
+#include "ace/OS_NS_unistd.h"
+
+ACE_RCSID(server, Handle_L_Pipe, "$Id$")
+
+#if !defined (ACE_LACKS_UNIX_DOMAIN_SOCKETS)
+
+// Uppercase N bytes of S.
+
+char *
+Handle_L_Pipe::upper_case (char s[], int n)
+{
+ while (--n >= 0)
+ if (ACE_OS::ace_islower (s[n]))
+ s[n] = ACE_OS::ace_toupper (s[n]);
+
+ return s;
+}
+
+int
+Handle_L_Pipe::handle_input (ACE_HANDLE)
+{
+ ACE_LSOCK_Stream new_local_stream;
+ int n;
+ ACE_HANDLE fd1 = ACE_INVALID_HANDLE;
+ ACE_HANDLE fd2 = ACE_INVALID_HANDLE;
+ char buf[BUFSIZ];
+
+ if (this->accept (new_local_stream) == -1)
+ return -1;
+
+ if (new_local_stream.recv_handle (fd1) == -1
+ || new_local_stream.recv_handle (fd2) == -1)
+ return -1;
+ else
+ ACE_DEBUG ((LM_INFO,
+ ACE_TEXT ("received file descriptors %d and %d\n"),
+ fd1,
+ fd2));
+
+ if ((n = ACE_OS::read (fd1, buf, sizeof buf)) == -1)
+ return -1;
+ else if (ACE_OS::write (fd2, this->upper_case (buf, n), n) == -1)
+ return -1;
+ if (ACE_OS::close (fd1) == -1
+ || ACE_OS::close (fd2) == -1)
+ return -1;
+ if (new_local_stream.close () == -1)
+ return -1;
+
+ return 0;
+}
+
+const ACE_TCHAR *Handle_L_Pipe::DEFAULT_RENDEZVOUS = ACE_TEXT ("/tmp/foo_pipe");
+
+#if !defined (__ACE_INLINE__)
+#include "Handle_L_Pipe.i"
+#endif /* __ACE_INLINE__ */
+
+Handle_L_Pipe local_pipe;
+ACE_Service_Object_Type lp (&local_pipe, ACE_TEXT ("Local_Pipe"));
+
+#endif /* ACE_LACKS_UNIX_DOMAIN_SOCKETS */
diff --git a/ACE/examples/Service_Configurator/IPC-tests/server/Handle_L_Pipe.h b/ACE/examples/Service_Configurator/IPC-tests/server/Handle_L_Pipe.h
new file mode 100644
index 00000000000..51d5bae1dac
--- /dev/null
+++ b/ACE/examples/Service_Configurator/IPC-tests/server/Handle_L_Pipe.h
@@ -0,0 +1,55 @@
+// -*- C++ -*-
+// $Id$
+
+// Handle connections from local UNIX domain sockets that are sending
+// end-points from a pipe!
+
+#ifndef _HANDLE_L_PIPE_H
+#define _HANDLE_L_PIPE_H
+
+#include "ace/Service_Config.h"
+#include "ace/Reactor.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/Service_Types.h"
+#include "ace/UNIX_Addr.h"
+#include "ace/LSOCK_Acceptor.h"
+#include "ace/svc_export.h"
+
+#if !defined (ACE_LACKS_UNIX_DOMAIN_SOCKETS)
+
+class ACE_Svc_Export Handle_L_Pipe : public ACE_Service_Object, public ACE_LSOCK_Acceptor
+{
+public:
+ Handle_L_Pipe (void);
+ ~Handle_L_Pipe (void);
+ virtual int init (int argc, ACE_TCHAR *argv[]);
+ virtual int info (ACE_TCHAR **, size_t) const;
+ virtual int fini (void);
+
+private:
+ int open (const ACE_UNIX_Addr &suap, int async = 0);
+ virtual ACE_HANDLE get_handle (void) const;
+ virtual int handle_input (ACE_HANDLE fd);
+ virtual int handle_close (ACE_HANDLE fd, ACE_Reactor_Mask);
+
+ char *upper_case (char s[], int n);
+
+ ACE_TCHAR rendezvous[MAXPATHLEN + 1];
+ static const ACE_TCHAR *DEFAULT_RENDEZVOUS;
+};
+
+extern ACE_Service_Object_Type lp;
+
+#if defined (__ACE_INLINE__)
+#define ACE_INLINE inline
+#include "Handle_L_Pipe.i"
+#else
+#define ACE_INLINE
+#endif /* __ACE_INLINE__ */
+
+#endif /* ACE_LACKS_UNIX_DOMAIN_SOCKETS */
+#endif /* _HANDLE_L_PIPE_H */
diff --git a/ACE/examples/Service_Configurator/IPC-tests/server/Handle_L_Pipe.i b/ACE/examples/Service_Configurator/IPC-tests/server/Handle_L_Pipe.i
new file mode 100644
index 00000000000..ce978aa85ea
--- /dev/null
+++ b/ACE/examples/Service_Configurator/IPC-tests/server/Handle_L_Pipe.i
@@ -0,0 +1,96 @@
+/* -*- C++ -*- */
+// $Id$
+
+#include "ace/Get_Opt.h"
+#include "ace/OS_NS_stdio.h"
+#include "ace/OS_NS_string.h"
+#include "ace/OS_NS_unistd.h"
+
+ACE_INLINE
+Handle_L_Pipe::~Handle_L_Pipe (void)
+{
+}
+
+ACE_INLINE
+Handle_L_Pipe::Handle_L_Pipe (void)
+{
+}
+
+ACE_INLINE int
+Handle_L_Pipe::open (const ACE_UNIX_Addr &suap, int async)
+{
+ if (this->ACE_LSOCK_Acceptor::open (suap) == -1)
+ return -1;
+ else if (async && this->ACE_LSOCK_Acceptor::enable (ACE_SIGIO) == -1)
+ return -1;
+ else
+ return 0;
+}
+
+ACE_INLINE int
+Handle_L_Pipe::info (ACE_TCHAR **strp, size_t length) const
+{
+ ACE_TCHAR buf[BUFSIZ];
+ ACE_UNIX_Addr sa;
+
+ if (ACE_LSOCK_Acceptor::get_local_addr (sa) == -1)
+ return -1;
+
+ ACE_OS::strcpy (buf, ACE_TEXT_CHAR_TO_TCHAR (sa.get_path_name ()));
+ ACE_OS::strcat (buf, ACE_TEXT (" # tests local pipe\n"));
+
+ if (*strp == 0 && (*strp = ACE_OS::strdup (buf)) == 0)
+ return -1;
+ else
+ ACE_OS::strncpy (*strp, buf, length);
+ return ACE_OS::strlen (buf);
+}
+
+ACE_INLINE int
+Handle_L_Pipe::init (int argc, ACE_TCHAR *argv[])
+{
+ ACE_UNIX_Addr sup;
+ const ACE_TCHAR *r = Handle_L_Pipe::DEFAULT_RENDEZVOUS;
+ ACE_Get_Opt get_opt (argc, argv, ACE_TEXT ("r:"), 0);
+
+ for (int c; (c = get_opt ()) != -1; )
+ switch (c)
+ {
+ case 'r':
+ r = get_opt.opt_arg ();
+ break;
+ default:
+ break;
+ }
+
+ ACE_OS::strncpy (this->rendezvous, r, MAXPATHLEN);
+ ACE_OS::unlink (this->rendezvous);
+ sup.set (this->rendezvous);
+ if (this->open (sup) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("%p\n"), ACE_TEXT ("open")), -1);
+ else if (ACE_Reactor::instance ()->register_handler
+ (this, ACE_Event_Handler::ACCEPT_MASK) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("%p\n"),
+ ACE_TEXT ("registering service with ACE_Reactor")), -1);
+ return 0;
+}
+
+ACE_INLINE int
+Handle_L_Pipe::fini (void)
+{
+ return ACE_Reactor::instance ()->remove_handler
+ (this, ACE_Event_Handler::ACCEPT_MASK);
+}
+
+ACE_INLINE int
+Handle_L_Pipe::get_handle (void) const
+{
+ return ACE_LSOCK_Acceptor::get_handle ();
+}
+
+ACE_INLINE int
+Handle_L_Pipe::handle_close (ACE_HANDLE, ACE_Reactor_Mask)
+{
+ this->ACE_LSOCK_Acceptor::close ();
+ return ACE_OS::unlink (this->rendezvous);
+}
diff --git a/ACE/examples/Service_Configurator/IPC-tests/server/Handle_L_SPIPE.cpp b/ACE/examples/Service_Configurator/IPC-tests/server/Handle_L_SPIPE.cpp
new file mode 100644
index 00000000000..9bbb4e7ead7
--- /dev/null
+++ b/ACE/examples/Service_Configurator/IPC-tests/server/Handle_L_SPIPE.cpp
@@ -0,0 +1,18 @@
+// $Id$
+
+#include "Handle_L_SPIPE.h"
+
+ACE_RCSID(server, Handle_L_SPIPE, "$Id$")
+
+#if !defined (__ACE_INLINE__)
+#include "Handle_L_SPIPE.i"
+#endif /* __ACE_INLINE__ */
+
+#if defined (ACE_HAS_STREAM_PIPES)
+
+const ACE_TCHAR *Handle_L_SPIPE::DEFAULT_RENDEZVOUS = ACE_TEXT ("/tmp/foo_spipe");
+
+Handle_L_SPIPE local_spipe;
+ACE_Service_Object_Type lsp (&local_spipe, ACE_TEXT ("Local_SPIPE"));
+
+#endif /* ACE_HAS_STREAM_PIPES */
diff --git a/ACE/examples/Service_Configurator/IPC-tests/server/Handle_L_SPIPE.h b/ACE/examples/Service_Configurator/IPC-tests/server/Handle_L_SPIPE.h
new file mode 100644
index 00000000000..02a4aba2044
--- /dev/null
+++ b/ACE/examples/Service_Configurator/IPC-tests/server/Handle_L_SPIPE.h
@@ -0,0 +1,52 @@
+/* -*- C++ -*- */
+// $Id$
+
+/* Handle connections from local UNIX ACE_SPIPE */
+/* Read from a well known ACE_SPIPE and write to stdout. */
+
+#ifndef _HANDLE_L_SPIPE_H
+#define _HANDLE_L_SPIPE_H
+
+#include "ace/Service_Config.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/Service_Types.h"
+#include "ace/SPIPE_Acceptor.h"
+#include "ace/Log_Msg.h"
+#include "ace/svc_export.h"
+
+#if defined (ACE_HAS_STREAM_PIPES)
+
+class ACE_Svc_Export Handle_L_SPIPE : public ACE_Service_Object, public ACE_SPIPE_Acceptor
+{
+public:
+ Handle_L_SPIPE (void);
+ virtual int init (int argc, ACE_TCHAR *argv[]);
+ virtual int info (ACE_TCHAR **, size_t) const;
+ virtual int fini (void);
+
+private:
+ int open (const ACE_SPIPE_Addr &rendezvous_spipe);
+ virtual int get_handle (void) const;
+ virtual int handle_input (int fd);
+ virtual int handle_close (int fd, ACE_Reactor_Mask);
+
+ static const ACE_TCHAR *DEFAULT_RENDEZVOUS;
+};
+
+extern ACE_Service_Object_Type lsp;
+
+#if defined (__ACE_INLINE__)
+#define ACE_INLINE inline
+#include "Handle_L_SPIPE.i"
+#else
+#define ACE_INLINE
+#endif /* __ACE_INLINE__ */
+
+#endif /* _HANDLE_L_SPIPE_H */
+
+
+#endif /* ACE_HAS_STREAM_PIPES */
diff --git a/ACE/examples/Service_Configurator/IPC-tests/server/Handle_L_SPIPE.i b/ACE/examples/Service_Configurator/IPC-tests/server/Handle_L_SPIPE.i
new file mode 100644
index 00000000000..910938d8648
--- /dev/null
+++ b/ACE/examples/Service_Configurator/IPC-tests/server/Handle_L_SPIPE.i
@@ -0,0 +1,131 @@
+// -*- C++ -*-
+//
+// $Id$
+
+
+#include "ace/SPIPE_Stream.h"
+
+#if defined (ACE_HAS_STREAM_PIPES)
+
+#include "ace/Reactor.h"
+#include "ace/Get_Opt.h"
+#include "ace/OS_NS_stdio.h"
+#include "ace/OS_NS_unistd.h"
+#include "ace/OS_NS_string.h"
+
+
+ACE_INLINE
+Handle_L_SPIPE::Handle_L_SPIPE (void)
+{
+}
+
+ACE_INLINE int
+Handle_L_SPIPE::open (const ACE_SPIPE_Addr &rendezvous_spipe)
+{
+ if (this->ACE_SPIPE_Acceptor::open (rendezvous_spipe) == -1)
+ return -1;
+ else
+ return 0;
+}
+
+ACE_INLINE int
+Handle_L_SPIPE::info (ACE_TCHAR **strp, size_t length) const
+{
+ ACE_TCHAR buf[BUFSIZ];
+ ACE_SPIPE_Addr sa;
+
+ if (ACE_SPIPE_Acceptor::get_local_addr (sa) == -1)
+ return -1;
+
+ ACE_OS::strcpy (buf, sa.get_path_name ());
+ ACE_OS::strcat (buf, ACE_TEXT (" # tests local STREAM pipe\n"));
+
+ if (*strp == 0 && (*strp = ACE_OS::strdup (buf)) == 0)
+ return -1;
+ else
+ ACE_OS::strncpy (*strp, buf, length);
+ return ACE_OS::strlen (buf);
+}
+
+ACE_INLINE int
+Handle_L_SPIPE::init (int argc, ACE_TCHAR *argv[])
+{
+ ACE_SPIPE_Addr susp;
+ const ACE_TCHAR *rendezvous = Handle_L_SPIPE::DEFAULT_RENDEZVOUS;
+ ACE_Get_Opt get_opt (argc, argv, ACE_TEXT ("r:"), 0);
+
+ for (int c; (c = get_opt ()) != -1; )
+ switch (c)
+ {
+ case 'r':
+ rendezvous = get_opt.opt_arg ();
+ break;
+ default:
+ break;
+ }
+
+ ACE_OS::unlink (rendezvous);
+ susp.set (rendezvous);
+ if (this->open (susp) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("%p\n"), ACE_TEXT ("open")), -1);
+ else if (ACE_Reactor::instance ()->register_handler
+ (this, ACE_Event_Handler::ACCEPT_MASK) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("registering service with ACE_Reactor")),
+ -1);
+ return 0;
+}
+
+ACE_INLINE int
+Handle_L_SPIPE::fini (void)
+{
+ return ACE_Reactor::instance ()->remove_handler
+ (this, ACE_Event_Handler::ACCEPT_MASK);
+}
+
+ACE_INLINE int
+Handle_L_SPIPE::get_handle (void) const
+{
+ return ACE_SPIPE::get_handle();
+}
+
+ACE_INLINE int
+Handle_L_SPIPE::handle_input (int)
+{
+ ACE_SPIPE_Stream new_spipe;
+ char buf[PIPE_BUF];
+ ACE_Str_Buf msg (buf, 0, sizeof buf);
+ int flags = 0;
+
+ /* Accept communication requests */
+ if (this->ACE_SPIPE_Acceptor::accept (new_spipe) == -1)
+ return -1;
+ else
+ {
+ ACE_SPIPE_Addr sa;
+
+ new_spipe.get_remote_addr (sa);
+
+ ACE_DEBUG ((LM_INFO,
+ ACE_TEXT ("accepted request from %s (gid = %d, uid = %d)\n"),
+ sa.get_path_name (), sa.group_id (), sa.user_id ()));
+ }
+
+ while (new_spipe.recv ((ACE_Str_Buf *) 0, &msg, &flags) >= 0)
+ if (msg.len != 0)
+ ACE_OS::write (ACE_STDOUT, (const char *) msg.buf, (int) msg.len);
+ else
+ break;
+
+ if (new_spipe.close () == -1)
+ return -1;
+ return 0;
+}
+
+ACE_INLINE int
+Handle_L_SPIPE::handle_close (int, ACE_Reactor_Mask)
+{
+ return this->ACE_SPIPE_Acceptor::remove ();
+}
+#endif /* ACE_HAS_STREAM_PIPES */
diff --git a/ACE/examples/Service_Configurator/IPC-tests/server/Handle_L_Stream.cpp b/ACE/examples/Service_Configurator/IPC-tests/server/Handle_L_Stream.cpp
new file mode 100644
index 00000000000..074f0057e74
--- /dev/null
+++ b/ACE/examples/Service_Configurator/IPC-tests/server/Handle_L_Stream.cpp
@@ -0,0 +1,22 @@
+// $Id$
+
+#include "Handle_L_Stream.h"
+
+ACE_RCSID(server, Handle_L_Stream, "$Id$")
+
+#if !defined (ACE_LACKS_UNIX_DOMAIN_SOCKETS)
+
+// Static variables.
+
+const ACE_TCHAR *Handle_L_Stream::DEFAULT_RENDEZVOUS = ACE_TEXT ("/tmp/foo_stream");
+char *Handle_L_Stream::login_name = 0;
+char Handle_L_Stream::login[ACE_MAX_USERID];
+
+#if !defined (__ACE_INLINE__)
+#include "Handle_L_Stream.i"
+#endif /* __ACE_INLINE__ */
+
+Handle_L_Stream local_stream;
+ACE_Service_Object_Type ls (&local_stream, ACE_TEXT ("Local_Stream"));
+
+#endif /* ACE_LACKS_UNIX_DOMAIN_SOCKETS */
diff --git a/ACE/examples/Service_Configurator/IPC-tests/server/Handle_L_Stream.h b/ACE/examples/Service_Configurator/IPC-tests/server/Handle_L_Stream.h
new file mode 100644
index 00000000000..912af48a292
--- /dev/null
+++ b/ACE/examples/Service_Configurator/IPC-tests/server/Handle_L_Stream.h
@@ -0,0 +1,53 @@
+// -*- C++ -*-
+// $Id$
+
+// Handle connections from local UNIX domain sockets.
+
+#ifndef _HANDLE_L_STREAM_H
+#define _HANDLE_L_STREAM_H
+
+#include "ace/Service_Config.h"
+#include "ace/Reactor.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/Service_Types.h"
+#include "ace/UNIX_Addr.h"
+#include "ace/LSOCK_Acceptor.h"
+#include "ace/svc_export.h"
+
+#if !defined (ACE_LACKS_UNIX_DOMAIN_SOCKETS)
+
+class ACE_Svc_Export Handle_L_Stream : public ACE_Service_Object, public ACE_LSOCK_Acceptor
+{
+public:
+ Handle_L_Stream (void);
+ ~Handle_L_Stream (void);
+ virtual int init (int argc, ACE_TCHAR *argv[]);
+ virtual int info (ACE_TCHAR **, size_t) const;
+ virtual int fini (void);
+
+private:
+ int open (const ACE_UNIX_Addr &suas, int async = 0);
+ virtual ACE_HANDLE get_handle (void) const;
+ virtual int handle_input (ACE_HANDLE fd);
+ virtual int handle_close (ACE_HANDLE fd, ACE_Reactor_Mask);
+
+ ACE_TCHAR rendezvous[MAXPATHLEN + 1];
+ static const ACE_TCHAR *DEFAULT_RENDEZVOUS;
+ static char *login_name;
+ static char login[ACE_MAX_USERID];
+};
+
+extern ACE_Service_Object_Type ls;
+
+#if defined (__ACE_INLINE__)
+#define ACE_INLINE inline
+#include "Handle_L_Stream.i"
+#else
+#define ACE_INLINE
+#endif /* __ACE_INLINE__ */
+#endif /* ACE_LACKS_UNIX_DOMAIN_SOCKETS */
+#endif /* _HANDLE_L_STREAM_H */
diff --git a/ACE/examples/Service_Configurator/IPC-tests/server/Handle_L_Stream.i b/ACE/examples/Service_Configurator/IPC-tests/server/Handle_L_Stream.i
new file mode 100644
index 00000000000..80b21852293
--- /dev/null
+++ b/ACE/examples/Service_Configurator/IPC-tests/server/Handle_L_Stream.i
@@ -0,0 +1,149 @@
+/* -*- C++ -*- */
+// $Id$
+
+#include "ace/Get_Opt.h"
+#include "ace/OS_NS_stdio.h"
+#include "ace/OS_NS_string.h"
+#include "ace/OS_NS_time.h"
+#include "ace/OS_NS_unistd.h"
+
+ACE_INLINE
+Handle_L_Stream::~Handle_L_Stream (void)
+{
+}
+
+ACE_INLINE
+Handle_L_Stream::Handle_L_Stream (void)
+{
+ if (Handle_L_Stream::login_name == 0)
+ Handle_L_Stream::login_name = ACE_OS::cuserid (Handle_L_Stream::login);
+}
+
+ACE_INLINE int
+Handle_L_Stream::open (const ACE_UNIX_Addr &suas,
+ int async)
+{
+ if (this->ACE_LSOCK_Acceptor::open (suas) == -1)
+ return -1;
+ else if (async && this->ACE_LSOCK_Acceptor::enable (ACE_SIGIO) == -1)
+ return -1;
+ else
+ return 0;
+}
+
+ACE_INLINE int
+Handle_L_Stream::info (ACE_TCHAR **strp, size_t length) const
+{
+ ACE_TCHAR buf[BUFSIZ];
+ ACE_UNIX_Addr sa;
+
+ if (this->get_local_addr (sa) == -1)
+ return -1;
+
+ ACE_OS::strcpy (buf, ACE_TEXT_CHAR_TO_TCHAR (sa.get_path_name ()));
+ ACE_OS::strcat (buf, ACE_TEXT (" # tests local ACE_Stream\n"));
+
+ if (*strp == 0 && (*strp = ACE_OS::strdup (buf)) == 0)
+ return -1;
+ else
+ ACE_OS::strncpy (*strp, buf, length);
+ return ACE_OS::strlen (buf);
+}
+
+ACE_INLINE int
+Handle_L_Stream::init (int argc, ACE_TCHAR *argv[])
+{
+ ACE_UNIX_Addr sus;
+ const ACE_TCHAR *r = Handle_L_Stream::DEFAULT_RENDEZVOUS;
+ ACE_Get_Opt get_opt (argc, argv, ACE_TEXT ("r:"), 0);
+
+ for (int c; (c = get_opt ()) != -1; )
+ switch (c)
+ {
+ case 'r':
+ r = get_opt.opt_arg ();
+ break;
+ default:
+ break;
+ }
+
+ ACE_OS::strncpy (this->rendezvous, r, MAXPATHLEN);
+ ACE_OS::unlink (this->rendezvous);
+ sus.set (this->rendezvous);
+
+ if (this->open (sus) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("%p\n"), ACE_TEXT ("open")), -1);
+ else if (ACE_Reactor::instance ()->register_handler
+ (this, ACE_Event_Handler::ACCEPT_MASK) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("%p\n"),
+ ACE_TEXT ("registering service with ACE_Reactor")), -1);
+ return 0;
+}
+
+ACE_INLINE int
+Handle_L_Stream::fini (void)
+{
+ return ACE_Reactor::instance ()->remove_handler
+ (this, ACE_Event_Handler::ACCEPT_MASK);
+}
+
+ACE_INLINE ACE_HANDLE
+Handle_L_Stream::get_handle (void) const
+{
+ return ACE_LSOCK_Acceptor::get_handle ();
+}
+
+ACE_INLINE int
+Handle_L_Stream::handle_input (ACE_HANDLE)
+{
+ ACE_LSOCK_Stream new_local_stream;
+ ACE_UNIX_Addr sa;
+ ACE_HANDLE handle = ACE_INVALID_HANDLE;
+ char buf[BUFSIZ];
+
+ if (this->accept (new_local_stream, &sa) == -1)
+ return -1;
+ else if (new_local_stream.recv_handle (handle) == -1)
+ return -1;
+ else
+ ACE_DEBUG ((LM_INFO,
+ ACE_TEXT ("received file descriptor %d on ACE_Stream %s\n"),
+ handle, sa.get_path_name ()));
+
+ ACE_OS::puts ("----------------------------------------");
+
+ for (;;)
+ {
+ ssize_t n = ACE_OS::read (handle, buf, sizeof buf);
+
+ if (n <= 0)
+ break;
+
+ ACE_OS::write (ACE_STDOUT, buf, n);
+ }
+
+ ACE_OS::puts ("----------------------------------------");
+
+ time_t t = ACE_OS::time (0L);
+ ACE_TCHAR *cs = ACE_OS::ctime (&t);
+
+ if (new_local_stream.send (4,
+ Handle_L_Stream::login_name,
+ ACE_OS::strlen (Handle_L_Stream::login_name),
+ ACE_TEXT_ALWAYS_CHAR (cs),
+ ACE_OS::strlen (cs)) == -1)
+ return -1;
+ else if (ACE_OS::close (handle) == -1)
+ return -1;
+ else if (new_local_stream.close () == -1)
+ return -1;
+ else
+ return 0;
+}
+
+ACE_INLINE int
+Handle_L_Stream::handle_close (ACE_HANDLE, ACE_Reactor_Mask)
+{
+ this->ACE_LSOCK_Acceptor::close ();
+ return ACE_OS::unlink (this->rendezvous);
+}
diff --git a/ACE/examples/Service_Configurator/IPC-tests/server/Handle_R_Dgram.cpp b/ACE/examples/Service_Configurator/IPC-tests/server/Handle_R_Dgram.cpp
new file mode 100644
index 00000000000..0cab7190ca8
--- /dev/null
+++ b/ACE/examples/Service_Configurator/IPC-tests/server/Handle_R_Dgram.cpp
@@ -0,0 +1,38 @@
+// $Id$
+
+#include "Handle_R_Dgram.h"
+
+ACE_RCSID(server, Handle_R_Dgram, "Handle_R_Dgram.cpp,v 4.2 1998/07/31 22:55:19 gonzo Exp")
+
+#if defined (SunOS4)
+extern "C"
+{
+ int init (void);
+ int fini (void);
+ void __sti__Handle_R_Dgram_C_init_();
+ void __std__Handle_R_Dgram_C_init_();
+}
+
+int
+init (void)
+{
+ __sti__Handle_R_Dgram_C_init_();
+ return 0;
+}
+
+int
+fini (void)
+{
+ __std__Handle_R_Dgram_C_init_();
+ return 0;
+}
+#endif /* SunOS4 */
+
+unsigned short Handle_R_Dgram::DEFAULT_PORT = ACE_DEFAULT_SERVER_PORT;
+
+#if !defined (__ACE_INLINE__)
+#include "Handle_R_Dgram.i"
+#endif /* __ACE_INLINE__ */
+
+Handle_R_Dgram remote_dgram;
+ACE_Service_Object_Type rd (&remote_dgram, ACE_TEXT ("Remote_Dgram"));
diff --git a/ACE/examples/Service_Configurator/IPC-tests/server/Handle_R_Dgram.h b/ACE/examples/Service_Configurator/IPC-tests/server/Handle_R_Dgram.h
new file mode 100644
index 00000000000..858d72ff993
--- /dev/null
+++ b/ACE/examples/Service_Configurator/IPC-tests/server/Handle_R_Dgram.h
@@ -0,0 +1,47 @@
+// -*- C++ -*-
+// $Id$
+
+/* Handles INET datagram messages from remote hosts. */
+
+#ifndef _HANDLE_R_DGRAM_H
+#define _HANDLE_R_DGRAM_H
+
+#include "ace/Service_Config.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/Service_Types.h"
+#include "ace/INET_Addr.h"
+#include "ace/SOCK_Dgram.h"
+#include "ace/Log_Msg.h"
+#include "ace/svc_export.h"
+
+class ACE_Svc_Export Handle_R_Dgram : public ACE_Service_Object, public ACE_SOCK_Dgram
+{
+public:
+ Handle_R_Dgram (void);
+ virtual int init (int argc, ACE_TCHAR *argv[]);
+ virtual int info (ACE_TCHAR **, size_t) const;
+ virtual int fini (void);
+
+private:
+ int open (const ACE_INET_Addr &r, int async = 0);
+ virtual ACE_HANDLE get_handle (void) const;
+ virtual int handle_input (ACE_HANDLE fd);
+ virtual int handle_close (ACE_HANDLE fd, ACE_Reactor_Mask);
+
+ static u_short DEFAULT_PORT;
+};
+
+extern ACE_Service_Object_Type rd;
+
+#if defined (__ACE_INLINE__)
+#define ACE_INLINE inline
+#include "Handle_R_Dgram.i"
+#else
+#define ACE_INLINE
+#endif /* __ACE_INLINE__ */
+
+#endif /* _HANDLE_R_DGRAM_H */
diff --git a/ACE/examples/Service_Configurator/IPC-tests/server/Handle_R_Dgram.i b/ACE/examples/Service_Configurator/IPC-tests/server/Handle_R_Dgram.i
new file mode 100644
index 00000000000..88212a988f0
--- /dev/null
+++ b/ACE/examples/Service_Configurator/IPC-tests/server/Handle_R_Dgram.i
@@ -0,0 +1,111 @@
+/* -*- C++ -*- */
+// $Id$
+
+#include "ace/Get_Opt.h"
+#include "ace/OS_NS_stdio.h"
+#include "ace/OS_NS_string.h"
+#include "ace/OS_NS_unistd.h"
+
+ACE_INLINE
+Handle_R_Dgram::Handle_R_Dgram (void)
+{
+}
+
+ACE_INLINE int
+Handle_R_Dgram::open (const ACE_INET_Addr &r, int async)
+{
+ if (this->ACE_SOCK_Dgram::open (r) == -1)
+ return -1;
+ else if (async && this->ACE_SOCK_Dgram::enable (ACE_SIGIO) == -1)
+ return -1;
+ else
+ return 0;
+}
+
+ACE_INLINE int
+Handle_R_Dgram::info (ACE_TCHAR **strp, size_t length) const
+{
+ ACE_TCHAR buf[BUFSIZ];
+ ACE_INET_Addr sa;
+
+ if (this->get_local_addr (sa) == -1)
+ return -1;
+
+ ACE_OS::sprintf (buf, ACE_TEXT ("%d/"), sa.get_port_number ());
+ ACE_OS::strcat (buf, ACE_TEXT ("udp # tests remote dgram\n"));
+
+ if (*strp == 0 && (*strp = ACE_OS::strdup (buf)) == 0)
+ return -1;
+ else
+ ACE_OS::strncpy (*strp, buf, length);
+ return ACE_OS::strlen (buf);
+}
+
+ACE_INLINE int
+Handle_R_Dgram::init (int argc, ACE_TCHAR *argv[])
+{
+ ACE_INET_Addr sidg (Handle_R_Dgram::DEFAULT_PORT);
+ ACE_Get_Opt get_opt (argc, argv, ACE_TEXT ("p:"), 0);
+
+ for (int c; (c = get_opt ()) != -1; )
+ switch (c)
+ {
+ case 'p':
+ sidg.set (ACE_OS::atoi (get_opt.opt_arg ()));
+ break;
+ default:
+ break;
+ }
+
+ if (this->open (sidg) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("%p\n"), ACE_TEXT ("open")), -1);
+ else if (ACE_Reactor::instance ()->register_handler
+ (this, ACE_Event_Handler::ACCEPT_MASK) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("%p\n"),
+ ACE_TEXT ("registering service with ACE_Reactor")), -1);
+ return 0;
+}
+
+ACE_INLINE int
+Handle_R_Dgram::fini (void)
+{
+ return ACE_Reactor::instance ()->remove_handler
+ (this, ACE_Event_Handler::ACCEPT_MASK);
+}
+
+ACE_INLINE ACE_HANDLE
+Handle_R_Dgram::get_handle (void) const
+{
+ return ACE_SOCK_Dgram::get_handle ();
+}
+
+ACE_INLINE int
+Handle_R_Dgram::handle_input (ACE_HANDLE)
+{
+ ACE_INET_Addr sa;
+ char buf[8 * 1024]; /* 8 k buffer */
+ ssize_t n = this->recv (buf, sizeof buf, sa);
+
+ if (n == -1)
+ return -1;
+ else
+ ACE_DEBUG ((LM_INFO,
+ ACE_TEXT ("received datagram from host %C on port %d\n"),
+ sa.get_host_name (), sa.get_port_number ()));
+
+ ACE_OS::puts ("----------------------------------------");
+ ACE_OS::write (ACE_STDOUT, buf, n);
+
+ if (buf[n - 1] != '\n')
+ putchar ('\n');
+
+ ACE_OS::puts ("----------------------------------------");
+
+ return 0;
+}
+
+ACE_INLINE int
+Handle_R_Dgram::handle_close (ACE_HANDLE, ACE_Reactor_Mask)
+{
+ return this->ACE_SOCK_Dgram::close ();
+}
diff --git a/ACE/examples/Service_Configurator/IPC-tests/server/Handle_R_Stream.cpp b/ACE/examples/Service_Configurator/IPC-tests/server/Handle_R_Stream.cpp
new file mode 100644
index 00000000000..95553833e72
--- /dev/null
+++ b/ACE/examples/Service_Configurator/IPC-tests/server/Handle_R_Stream.cpp
@@ -0,0 +1,42 @@
+// $Id$
+
+#include "Handle_R_Stream.h"
+
+ACE_RCSID(server, Handle_R_Stream, "$Id$")
+
+#if defined (SunOS4)
+extern "C"
+{
+ int init (void);
+ int fini (void);
+ void __sti__Handle_R_Stream_C_recv_n_();
+ void __std__Handle_R_Stream_C_recv_n_();
+}
+
+int
+init (void)
+{
+ __sti__Handle_R_Stream_C_recv_n_();
+ return 0;
+}
+
+int
+fini (void)
+{
+ __std__Handle_R_Stream_C_recv_n_();
+ return 0;
+}
+#endif /* SunOS4 */
+
+// Static variables.
+
+u_short Handle_R_Stream::DEFAULT_PORT = ACE_DEFAULT_SERVER_PORT;
+char *Handle_R_Stream::login_name = 0;
+char Handle_R_Stream::login[ACE_MAX_USERID];
+
+#if !defined (__ACE_INLINE__)
+#include "Handle_R_Stream.i"
+#endif /* __ACE_INLINE__ */
+
+Handle_R_Stream remote_stream;
+ACE_Service_Object_Type rs (&remote_stream, ACE_TEXT("Remote_Stream"));
diff --git a/ACE/examples/Service_Configurator/IPC-tests/server/Handle_R_Stream.h b/ACE/examples/Service_Configurator/IPC-tests/server/Handle_R_Stream.h
new file mode 100644
index 00000000000..9878321cec8
--- /dev/null
+++ b/ACE/examples/Service_Configurator/IPC-tests/server/Handle_R_Stream.h
@@ -0,0 +1,53 @@
+// -*- C++ -*-
+//
+// $Id$
+
+/* Handle connections from remote INET connections. */
+
+#ifndef _HANDLE_R_STREAM_H
+#define _HANDLE_R_STREAM_H
+
+#include "ace/Service_Config.h"
+#include "ace/Reactor.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/Service_Types.h"
+#include "ace/SOCK_Stream.h"
+#include "ace/SOCK_Acceptor.h"
+#include "ace/INET_Addr.h"
+#include "ace/Log_Msg.h"
+#include "ace/svc_export.h"
+
+class ACE_Svc_Export Handle_R_Stream : public ACE_Service_Object, public ACE_SOCK_Acceptor
+{
+public:
+ Handle_R_Stream (void);
+ virtual int init (int argc, ACE_TCHAR *argv[]);
+ virtual int info (ACE_TCHAR **, size_t) const;
+ virtual int fini (void);
+
+private:
+ int open (const ACE_INET_Addr &sia, int async = 0);
+ virtual ACE_HANDLE get_handle (void) const;
+ virtual int handle_input (ACE_HANDLE fd);
+ virtual int handle_close (ACE_HANDLE fd, ACE_Reactor_Mask);
+
+ ACE_SOCK_Stream new_remote_stream;
+ static u_short DEFAULT_PORT;
+ static char *login_name;
+ static char login[ACE_MAX_USERID];
+};
+
+extern ACE_Service_Object_Type rs;
+
+#if defined (__ACE_INLINE__)
+#define ACE_INLINE inline
+#include "Handle_R_Stream.i"
+#else
+#define ACE_INLINE
+#endif /* __ACE_INLINE__ */
+
+#endif /* _HANDLE_R_STREAM_H */
diff --git a/ACE/examples/Service_Configurator/IPC-tests/server/Handle_R_Stream.i b/ACE/examples/Service_Configurator/IPC-tests/server/Handle_R_Stream.i
new file mode 100644
index 00000000000..f126cd13aee
--- /dev/null
+++ b/ACE/examples/Service_Configurator/IPC-tests/server/Handle_R_Stream.i
@@ -0,0 +1,153 @@
+/* -*- C++ -*- */
+// $Id$
+
+#include "ace/Get_Opt.h"
+#include "ace/WFMO_Reactor.h"
+#include "ace/OS_NS_stdio.h"
+#include "ace/OS_NS_string.h"
+#include "ace/OS_NS_time.h"
+#include "ace/OS_NS_unistd.h"
+
+ACE_INLINE
+Handle_R_Stream::Handle_R_Stream (void)
+{
+ if (Handle_R_Stream::login_name == 0)
+ Handle_R_Stream::login_name = ACE_OS::cuserid (Handle_R_Stream::login);
+}
+
+ACE_INLINE int
+Handle_R_Stream::open (const ACE_INET_Addr &sia, int async)
+{
+ if (this->ACE_SOCK_Acceptor::open (sia) == -1)
+ return -1;
+ else if (async && this->ACE_SOCK_Acceptor::enable (ACE_SIGIO) == -1)
+ return -1;
+ else
+ return 0;
+}
+
+ACE_INLINE int
+Handle_R_Stream::info (ACE_TCHAR **strp, size_t length) const
+{
+ ACE_TCHAR buf[BUFSIZ];
+ ACE_INET_Addr sa;
+
+ if (this->get_local_addr (sa) == -1)
+ return -1;
+
+ ACE_OS::sprintf (buf,
+ ACE_TEXT("%d/%s %s"),
+ sa.get_port_number (),
+ ACE_TEXT("tcp"),
+ ACE_TEXT("# tests remote stream\n"));
+
+ if (*strp == 0 && (*strp = ACE_OS::strdup (buf)) == 0)
+ return -1;
+ else
+ ACE_OS::strncpy (*strp, buf, length);
+ return ACE_OS::strlen (buf);
+}
+
+ACE_INLINE int
+Handle_R_Stream::init (int argc, ACE_TCHAR *argv[])
+{
+ ACE_INET_Addr sis (Handle_R_Stream::DEFAULT_PORT);
+ ACE_Get_Opt get_opt (argc, argv, ACE_TEXT("p:"), 0);
+
+ for (int c; (c = get_opt ()) != -1; )
+ switch (c)
+ {
+ case 'p':
+ sis.set (ACE_OS::atoi (get_opt.opt_arg ()));
+ break;
+ default:
+ break;
+ }
+
+ if (this->open (sis) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "open"), -1);
+
+ else if (ACE_Reactor::instance ()->register_handler
+ (this, ACE_Event_Handler::ACCEPT_MASK) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "registering service with ACE_Reactor\n"),
+ -1);
+ return 0;
+}
+
+ACE_INLINE int
+Handle_R_Stream::fini (void)
+{
+ return ACE_Reactor::instance ()->remove_handler
+ (this, ACE_Event_Handler::ACCEPT_MASK);
+}
+
+ACE_INLINE ACE_HANDLE
+Handle_R_Stream::get_handle (void) const
+{
+ return ACE_SOCK_Acceptor::get_handle ();
+}
+
+ACE_INLINE int
+Handle_R_Stream::handle_input (ACE_HANDLE)
+{
+ char buf[BUFSIZ];
+ int bytes;
+
+ // Try to find out if the implementation of the reactor that we are
+ // using requires us to reset the event association for the newly
+ // created handle. This is because the newly created handle will
+ // inherit the properties of the listen handle, including its event
+ // associations.
+ int reset_new_handle =
+ ACE_Reactor::instance ()->uses_event_associations ();
+
+ if (this->accept (this->new_remote_stream, // stream
+ 0, // remote address
+ 0, // timeout
+ 1, // restart
+ reset_new_handle // reset new handler
+ ) == -1)
+ return -1;
+ else
+ ACE_DEBUG ((LM_INFO, "new_remote_stream fd = %d\n",
+ this->new_remote_stream.get_handle ()));
+
+ ACE_INET_Addr sa;
+
+ if (this->new_remote_stream.get_remote_addr (sa) == -1)
+ return -1;
+
+ ACE_DEBUG ((LM_INFO,
+ "accepted from host %s at port %d\n",
+ sa.get_host_name (),
+ sa.get_port_number ()));
+
+ ACE_OS::puts (ACE_TEXT ("----------------------------------------"));
+
+ while ((bytes = this->new_remote_stream.recv (buf, sizeof buf)) > 0)
+ ACE_OS::write (ACE_STDOUT, buf, bytes);
+
+ ACE_OS::puts (ACE_TEXT ("----------------------------------------"));
+
+ time_t t = ACE_OS::time (0L);
+ ACE_TCHAR *cs = ACE_OS::ctime (&t);
+
+ if (this->new_remote_stream.send (4,
+ Handle_R_Stream::login_name,
+ ACE_OS::strlen (Handle_R_Stream::login_name),
+ cs,
+ ACE_OS::strlen (cs)) == -1)
+ return -1;
+
+ if (this->new_remote_stream.close () == -1)
+ return -1;
+
+ return 0;
+}
+
+ACE_INLINE int
+Handle_R_Stream::handle_close (ACE_HANDLE, ACE_Reactor_Mask)
+{
+ return this->ACE_SOCK_Acceptor::close ();
+}
diff --git a/ACE/examples/Service_Configurator/IPC-tests/server/Handle_Thr_Stream.cpp b/ACE/examples/Service_Configurator/IPC-tests/server/Handle_Thr_Stream.cpp
new file mode 100644
index 00000000000..fb53c0f8d70
--- /dev/null
+++ b/ACE/examples/Service_Configurator/IPC-tests/server/Handle_Thr_Stream.cpp
@@ -0,0 +1,195 @@
+// $Id$
+
+#if !defined (ACE_HANDLE_THR_STREAM_C)
+#define ACE_HANDLE_THR_STREAM_C
+
+#include "ace/OS_NS_stdio.h"
+#include "ace/OS_NS_string.h"
+#include "ace/OS_NS_unistd.h"
+#include "ace/Get_Opt.h"
+#include "ace/INET_Addr.h"
+#include "ace/TLI_Acceptor.h"
+#include "Handle_Thr_Stream.h"
+
+ACE_RCSID(server, Handle_Thr_Stream, "$Id$")
+
+#if defined (ACE_HAS_THREADS)
+
+#include "ace/OS_NS_time.h"
+
+// Shorthand names.
+#define SVH SVC_HANDLER
+#define PR_AC_1 ACE_PEER_ACCEPTOR_1
+#define PR_AC_2 ACE_PEER_ACCEPTOR_2
+#define PR_ST_1 ACE_PEER_STREAM_1
+#define PR_ST_2 ACE_PEER_STREAM_2
+
+template <class SVH, PR_AC_1>
+Handle_Thr_Acceptor<SVH, PR_AC_2>::~Handle_Thr_Acceptor (void)
+{
+}
+
+template <class SVH, PR_AC_1>
+Handle_Thr_Acceptor<SVH, PR_AC_2>::Handle_Thr_Acceptor (void)
+ : thr_flags_ (THR_DETACHED | THR_NEW_LWP)
+{
+}
+
+template <class SVH, PR_AC_1> int
+Handle_Thr_Acceptor<SVH, PR_AC_2>::info (ACE_TCHAR **strp,
+ size_t length) const
+{
+ ACE_TCHAR buf[BUFSIZ];
+ ACE_INET_Addr sa;
+
+ if (this->acceptor ().get_local_addr (sa) == -1)
+ return -1;
+
+ ACE_OS::sprintf (buf, ACE_TEXT("%d/"), sa.get_port_number ());
+ ACE_OS::strcat (buf, ACE_TEXT("tcp # tests threaded remote stream\n"));
+
+ if (*strp == 0 && (*strp = ACE_OS::strdup (buf)) == 0)
+ return -1;
+ else
+ ACE_OS::strncpy (*strp, buf, length);
+ return ACE_OS::strlen (buf);
+}
+
+template <class SVH, PR_AC_1> int
+Handle_Thr_Acceptor<SVH, PR_AC_2>::init (int argc, ACE_TCHAR *argv[])
+{
+ ACE_INET_Addr local_addr (ACE_DEFAULT_THR_PORT);
+ int n_threads = ACE_DEFAULT_THREADS;
+
+ ACE_Get_Opt get_opt (argc, argv, ACE_TEXT("p:t:"), 0);
+
+ for (int c; (c = get_opt ()) != -1; )
+ switch (c)
+ {
+ case 'p':
+ local_addr.set (ACE_OS::atoi (get_opt.opt_arg ()));
+ break;
+ case 't':
+ n_threads = ACE_OS::atoi (get_opt.opt_arg ());
+ break;
+ default:
+ break;
+ }
+
+ // Initialize the threading strategy.
+ if (this->thr_strategy_.open (&this->thr_mgr_,
+ this->thr_flags_,
+ n_threads) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("%p\n"), ACE_TEXT ("open")), -1);
+
+ // Initialize the Acceptor base class, passing in the desired
+ // concurrency strategy.
+ else if (this->open (local_addr,
+ ACE_Reactor::instance (),
+ 0,
+ 0,
+ &this->thr_strategy_) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("%p\n"), ACE_TEXT ("open")), -1);
+ else
+ return 0;
+}
+
+template <class SVH, PR_AC_1> int
+Handle_Thr_Acceptor<SVH, PR_AC_2>::fini (void)
+{
+ return ACE_Reactor::instance ()->remove_handler
+ (this, ACE_Event_Handler::ACCEPT_MASK);
+}
+
+template <PR_ST_1>
+CLI_Stream<PR_ST_2>::CLI_Stream (ACE_Thread_Manager *thr_mgr)
+ : inherited (thr_mgr)
+{
+}
+
+template <PR_ST_1> int
+CLI_Stream<PR_ST_2>::close (u_long)
+{
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("(%t) client stream object closing down\n")));
+ this->peer ().close ();
+
+ // Must be allocated dynamically!
+ delete this;
+ return 0;
+}
+
+template <PR_ST_1> int
+CLI_Stream<PR_ST_2>::open (void *)
+{
+ ACE_INET_Addr sa;
+
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("(%t) client handle = %d\n"),
+ this->peer ().get_handle ()));
+
+ if (this->peer ().get_remote_addr (sa) == -1)
+ return -1;
+
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("(%t) accepted at port %d\n"),
+ sa.get_port_number ()));
+ return 0;
+}
+
+template <PR_ST_1> int
+CLI_Stream<PR_ST_2>::svc (void)
+{
+ char buf[BUFSIZ];
+ char login_name[ACE_MAX_USERID];
+ int bytes;
+
+ ACE_OS::puts ("----------------------------------------");
+
+ while ((bytes = this->peer ().recv (buf, sizeof buf)) > 0)
+ ACE_OS::write (ACE_STDOUT, buf, bytes);
+
+ ACE_OS::puts ("----------------------------------------");
+ ACE_OS::fflush (stdout);
+
+ time_t t = ACE_OS::time (0L);
+ ACE_OS::cuserid (login_name);
+ ACE_OS::sprintf (buf, "user %s %s",
+ login_name,
+ ACE_TEXT_ALWAYS_CHAR (ACE_OS::ctime ((const time_t *) &t)));
+
+ if (this->peer ().send_n (buf, ACE_OS::strlen (buf) + 1) == -1)
+ return -1;
+
+ ACE_DEBUG ((LM_DEBUG, "(%t) sent reply %s", buf));
+ return 0;
+}
+
+#undef SVH
+#undef PR_AC_1
+#undef PR_AC_2
+#undef PR_ST_1
+#undef PR_ST_2
+
+//----------------------------------------
+
+#if defined (ACE_HAS_TLI)
+#include "ace/TLI_Stream.h"
+#include "ace/TLI_Acceptor.h"
+#define THR_STREAM ACE_TLI_STREAM
+#define THR_ACCEPTOR ACE_TLI_ACCEPTOR
+#else
+#include "ace/SOCK_Stream.h"
+#include "ace/SOCK_Acceptor.h"
+#define THR_STREAM ACE_SOCK_STREAM
+#define THR_ACCEPTOR ACE_SOCK_ACCEPTOR
+#endif /* ACE_HAS_TLI */
+#include "ace/INET_Addr.h"
+
+typedef CLI_Stream <THR_STREAM> CLI_STREAM;
+typedef Handle_Thr_Acceptor<CLI_STREAM, THR_ACCEPTOR> HANDLE_THR_ACCEPTOR;
+
+// Service object.
+HANDLE_THR_ACCEPTOR remote_thr_stream;
+ACE_Service_Object_Type rts (&remote_thr_stream, ACE_TEXT("Remote_Thr_Stream"));
+
+#endif /* ACE_HAS_THREADS */
+#endif /* ACE_HANDLE_THR_STREAM_C */
diff --git a/ACE/examples/Service_Configurator/IPC-tests/server/Handle_Thr_Stream.h b/ACE/examples/Service_Configurator/IPC-tests/server/Handle_Thr_Stream.h
new file mode 100644
index 00000000000..994a70009c0
--- /dev/null
+++ b/ACE/examples/Service_Configurator/IPC-tests/server/Handle_Thr_Stream.h
@@ -0,0 +1,73 @@
+/* -*- C++ -*- */
+// $Id$
+
+#ifndef _HANDLE_THR_STREAM_H
+#define _HANDLE_THR_STREAM_H
+
+#include "ace/Acceptor.h"
+#include "ace/Svc_Handler.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/Service_Types.h"
+
+#if defined (ACE_HAS_THREADS)
+
+template <class SVC_HANDLER, ACE_PEER_ACCEPTOR_1>
+class Handle_Thr_Acceptor : public ACE_Strategy_Acceptor<SVC_HANDLER, ACE_PEER_ACCEPTOR_2>
+ // = TITLE
+ // This factory creates new <SVC_HANDLERS> and runs them with the
+ // configured <ACE_Thread_Strategy>.
+{
+public:
+ // = Initialization and termination.
+ Handle_Thr_Acceptor (void);
+ ~Handle_Thr_Acceptor (void);
+
+ // = Dynamic linking hooks.
+ virtual int init (int argc, ACE_TCHAR *argv[]);
+ virtual int info (ACE_TCHAR **, size_t) const;
+ virtual int fini (void);
+
+private:
+ ACE_Thread_Manager thr_mgr_;
+ // Thread manager.
+
+ ACE_Thread_Strategy<SVC_HANDLER> thr_strategy_;
+ // Threading strategy.
+
+ int thr_flags_;
+ // Threading flags.
+};
+
+template <ACE_PEER_STREAM_1>
+class CLI_Stream : public ACE_Svc_Handler<ACE_PEER_STREAM_2, ACE_MT_SYNCH>
+ // = TITLE
+ // This class interacts with the client, running in a separate
+ // thread and handles connections from remote TCP/IP connections.
+{
+public:
+ CLI_Stream (ACE_Thread_Manager * = 0);
+
+ virtual int open (void *);
+ // Open the service.
+
+ virtual int close (u_long);
+ // Close down the service.
+
+ virtual int svc (void);
+ // Execute the service.
+
+protected:
+ typedef ACE_Svc_Handler<ACE_PEER_STREAM_2, ACE_MT_SYNCH> inherited;
+};
+
+extern ACE_Service_Object_Type rts;
+
+#if defined (ACE_TEMPLATES_REQUIRE_SOURCE)
+#include "Handle_Thr_Stream.cpp"
+#endif /* ACE_TEMPLATES_REQUIRE_SOURCE */
+#endif /* ACE_HAS_THREADS */
+#endif /* _HANDLE_THR_STREAM_H */
diff --git a/ACE/examples/Service_Configurator/IPC-tests/server/Handle_Timeout.cpp b/ACE/examples/Service_Configurator/IPC-tests/server/Handle_Timeout.cpp
new file mode 100644
index 00000000000..9eccf88ef43
--- /dev/null
+++ b/ACE/examples/Service_Configurator/IPC-tests/server/Handle_Timeout.cpp
@@ -0,0 +1,36 @@
+// $Id$
+
+#include "Handle_Timeout.h"
+
+ACE_RCSID(server, Handle_Timeout, "$Id$")
+
+#if defined (SunOS4)
+extern "C"
+{
+ int init (void);
+ int fini (void);
+ void __sti__Handle_Timeout_C_init_();
+ void __std__Handle_Timeout_C_init_();
+}
+
+int
+init (void)
+{
+ __sti__Handle_Timeout_C_init_();
+ return 0;
+}
+
+int
+fini (void)
+{
+ __std__Handle_Timeout_C_init_();
+ return 0;
+}
+#endif /* SunOS4 */
+
+#if !defined (__ACE_INLINE__)
+#include "Handle_Timeout.i"
+#endif /* __ACE_INLINE__ */
+
+Handle_Timeout timer_1;
+ACE_Service_Object_Type t1 (&timer_1, ACE_TEXT("Timer_1"));
diff --git a/ACE/examples/Service_Configurator/IPC-tests/server/Handle_Timeout.h b/ACE/examples/Service_Configurator/IPC-tests/server/Handle_Timeout.h
new file mode 100644
index 00000000000..88b6e673aaf
--- /dev/null
+++ b/ACE/examples/Service_Configurator/IPC-tests/server/Handle_Timeout.h
@@ -0,0 +1,45 @@
+// -*- C++ -*-
+//
+// $Id$
+
+/* Handles timeouts. */
+
+#ifndef _HANDLE_TIMEOUT_H
+#define _HANDLE_TIMEOUT_H
+
+#include "ace/Service_Config.h"
+#include "ace/Reactor.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/Service_Types.h"
+#include "ace/Log_Msg.h"
+#include "ace/svc_export.h"
+
+class ACE_Svc_Export Handle_Timeout : public ACE_Service_Object
+{
+public:
+ Handle_Timeout (void);
+ virtual int init (int argc, ACE_TCHAR *argv[]);
+ virtual int info (ACE_TCHAR **, size_t) const;
+ virtual int fini (void);
+
+private:
+ virtual ACE_HANDLE get_handle (void) const;
+ virtual int handle_timeout (const ACE_Time_Value &tv, const void *arg);
+
+ int count;
+};
+
+extern ACE_Service_Object_Type t1;
+
+#if defined (__ACE_INLINE__)
+#define ACE_INLINE inline
+#include "Handle_Timeout.i"
+#else
+#define ACE_INLINE
+#endif /* __ACE_INLINE__ */
+
+#endif /* _HANDLE_TIMEOUT_H */
diff --git a/ACE/examples/Service_Configurator/IPC-tests/server/Handle_Timeout.i b/ACE/examples/Service_Configurator/IPC-tests/server/Handle_Timeout.i
new file mode 100644
index 00000000000..346a22e773c
--- /dev/null
+++ b/ACE/examples/Service_Configurator/IPC-tests/server/Handle_Timeout.i
@@ -0,0 +1,86 @@
+/* -*- C++ -*- */
+// $Id$
+
+#include "ace/Service_Config.h"
+#include "ace/Get_Opt.h"
+#include "ace/OS_NS_stdio.h"
+#include "ace/OS_NS_string.h"
+
+ACE_INLINE
+Handle_Timeout::Handle_Timeout (void): count (0)
+{
+}
+
+ACE_INLINE int
+Handle_Timeout::info (ACE_TCHAR **strp, size_t length) const
+{
+ ACE_TCHAR buf[BUFSIZ];
+
+ ACE_OS::strcpy (buf, ACE_TEXT("# tests timeout facility\n"));
+
+ if (*strp == 0 && (*strp = ACE_OS::strdup (buf)) == 0)
+ return -1;
+ else
+ ACE_OS::strncpy (*strp, buf, length);
+ return ACE_OS::strlen (buf);
+}
+
+ACE_INLINE int
+Handle_Timeout::init (int argc, ACE_TCHAR *argv[])
+{
+ ACE_Time_Value delta (10);
+ ACE_Time_Value interval (1);
+ ACE_Get_Opt get_opt (argc, argv, ACE_TEXT("a:d:i:"), 0);
+ int arg = 0;
+
+ for (int c; (c = get_opt ()) != -1; )
+ switch (c)
+ {
+ case 'd':
+ delta.sec (ACE_OS::atoi (get_opt.opt_arg ()));
+ break;
+ case 'i':
+ interval.sec (ACE_OS::atoi (get_opt.opt_arg ()));
+ break;
+ case 'a':
+ arg = ACE_OS::atoi (get_opt.opt_arg ());
+ break;
+ default:
+ break;
+ }
+
+ if (ACE_Reactor::instance ()->schedule_timer (this,
+ reinterpret_cast<void *> (arg),
+ delta,
+ interval) == -1)
+ return -1;
+ else
+ return 0;
+}
+
+ACE_INLINE int
+Handle_Timeout::fini (void)
+{
+ return 0;
+}
+
+ACE_INLINE ACE_HANDLE
+Handle_Timeout::get_handle (void) const
+{
+ return ACE_INVALID_HANDLE;
+}
+
+ACE_INLINE int
+Handle_Timeout::handle_timeout (const ACE_Time_Value &tv,
+ const void *arg)
+{
+ if (this->count++ >= 10)
+ return -1; // Automatically cancel periodic timer...
+
+ // Cast arg to a long, first, because a pointer is the same
+ // size as a long on all current ACE platforms.
+ ACE_DEBUG ((LM_INFO,
+ ACE_TEXT ("time for this(%u) expired at (%d, %d) with arg = %d\n"),
+ this, tv.sec (), tv.usec (), (int) (long) arg));
+ return 0;
+}
diff --git a/ACE/examples/Service_Configurator/IPC-tests/server/Makefile.am b/ACE/examples/Service_Configurator/IPC-tests/server/Makefile.am
new file mode 100644
index 00000000000..58a8a80fccf
--- /dev/null
+++ b/ACE/examples/Service_Configurator/IPC-tests/server/Makefile.am
@@ -0,0 +1,106 @@
+## Process this file with automake to create Makefile.in
+##
+## $Id$
+##
+## This file was generated by MPC. Any changes made directly to
+## this file will be lost the next time it is generated.
+##
+## MPC Command:
+## /acebuilds/ACE_wrappers-repository/bin/mwc.pl -include /acebuilds/MPC/config -include /acebuilds/MPC/templates -feature_file /acebuilds/ACE_wrappers-repository/local.features -noreldefs -type automake -exclude build,Kokyu
+
+ACE_BUILDDIR = $(top_builddir)
+ACE_ROOT = $(top_srcdir)
+
+
+## Makefile.Svc_Cfg_IPC_Server_Lib.am
+
+if !BUILD_ACE_FOR_TAO
+
+noinst_LTLIBRARIES = libIPC_Tests_Server.la
+
+libIPC_Tests_Server_la_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR) \
+ -DACE_BUILD_SVC_DLL
+
+libIPC_Tests_Server_la_SOURCES = \
+ Handle_Broadcast.cpp \
+ Handle_L_CODgram.cpp \
+ Handle_L_Dgram.cpp \
+ Handle_L_FIFO.cpp \
+ Handle_L_Pipe.cpp \
+ Handle_L_SPIPE.cpp \
+ Handle_L_Stream.cpp \
+ Handle_R_Stream.cpp \
+ Handle_Thr_Stream.cpp \
+ Handle_Timeout.cpp
+
+noinst_HEADERS = \
+ Handle_Broadcast.h \
+ Handle_Broadcast.i \
+ Handle_L_CODgram.h \
+ Handle_L_CODgram.i \
+ Handle_L_Dgram.h \
+ Handle_L_Dgram.i \
+ Handle_L_FIFO.h \
+ Handle_L_FIFO.i \
+ Handle_L_Pipe.h \
+ Handle_L_Pipe.i \
+ Handle_L_SPIPE.h \
+ Handle_L_SPIPE.i \
+ Handle_L_Stream.h \
+ Handle_L_Stream.i \
+ Handle_R_Stream.h \
+ Handle_R_Stream.i \
+ Handle_Thr_Stream.h \
+ Handle_Timeout.h \
+ Handle_Timeout.i
+
+endif !BUILD_ACE_FOR_TAO
+
+## Makefile.Svc_Cfg_IPC_Server_Test.am
+
+if !BUILD_ACE_FOR_TAO
+noinst_PROGRAMS = server_test
+
+server_test_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+server_test_SOURCES = \
+ server_test.cpp \
+ Handle_Broadcast.h \
+ Handle_Broadcast.i \
+ Handle_L_CODgram.h \
+ Handle_L_CODgram.i \
+ Handle_L_Dgram.h \
+ Handle_L_Dgram.i \
+ Handle_L_FIFO.h \
+ Handle_L_FIFO.i \
+ Handle_L_Pipe.h \
+ Handle_L_Pipe.i \
+ Handle_L_SPIPE.h \
+ Handle_L_SPIPE.i \
+ Handle_L_Stream.h \
+ Handle_L_Stream.i \
+ Handle_R_Dgram.h \
+ Handle_R_Dgram.i \
+ Handle_R_Stream.h \
+ Handle_R_Stream.i \
+ Handle_Thr_Stream.h \
+ Handle_Timeout.h \
+ Handle_Timeout.i
+
+server_test_LDADD = \
+ libIPC_Tests_Server.la \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+endif !BUILD_ACE_FOR_TAO
+
+## Clean up template repositories, etc.
+clean-local:
+ -rm -f *~ *.bak *.rpo *.sym lib*.*_pure_* core core.*
+ -rm -f gcctemp.c gcctemp so_locations *.ics
+ -rm -rf cxx_repository ptrepository ti_files
+ -rm -rf templateregistry ir.out
+ -rm -rf ptrepository SunWS_cache Templates.DB
diff --git a/ACE/examples/Service_Configurator/IPC-tests/server/Svc_Cfg_IPC_Server.mpc b/ACE/examples/Service_Configurator/IPC-tests/server/Svc_Cfg_IPC_Server.mpc
new file mode 100644
index 00000000000..c44b40c6e32
--- /dev/null
+++ b/ACE/examples/Service_Configurator/IPC-tests/server/Svc_Cfg_IPC_Server.mpc
@@ -0,0 +1,30 @@
+// -*- MPC -*-
+// $Id$
+
+project(*Lib) : acelib {
+ avoids += ace_for_tao
+ sharedname = IPC_Tests_Server
+ dynamicflags += ACE_BUILD_SVC_DLL
+ Source_Files {
+ Handle_Broadcast.cpp
+ Handle_L_CODgram.cpp
+ Handle_L_Dgram.cpp
+ Handle_L_FIFO.cpp
+ Handle_L_Pipe.cpp
+ Handle_L_SPIPE.cpp
+ Handle_L_Stream.cpp
+ Handle_R_Stream.cpp
+ Handle_Thr_Stream.cpp
+ Handle_Timeout.cpp
+ }
+}
+
+project(*test) : aceexe {
+ avoids += ace_for_tao
+ exename = server_test
+ after += Svc_Cfg_IPC_Server_Lib
+ libs += IPC_Tests_Server
+ Source_Files {
+ server_test.cpp
+ }
+}
diff --git a/ACE/examples/Service_Configurator/IPC-tests/server/server_test.cpp b/ACE/examples/Service_Configurator/IPC-tests/server/server_test.cpp
new file mode 100644
index 00000000000..fe88a3eab8e
--- /dev/null
+++ b/ACE/examples/Service_Configurator/IPC-tests/server/server_test.cpp
@@ -0,0 +1,54 @@
+// $Id$
+
+// The main test driver for the dynamically configured server.
+
+#include "ace/OS_NS_unistd.h"
+#include "ace/Service_Config.h"
+#include "ace/Reactor.h"
+#include "ace/Log_Msg.h"
+#include "ace/Signal.h"
+#include "ace/Sig_Adapter.h"
+
+ACE_RCSID(server, server_test, "$Id$")
+
+int
+ACE_TMAIN (int argc, ACE_TCHAR *argv[])
+{
+ if (ACE_Service_Config::open (argc,
+ argv,
+ ACE_DEFAULT_LOGGER_KEY,
+ 0) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("ACE_Service_Config::open")),
+ -1);
+
+ // Create an adapter to end the event loop.
+ ACE_Sig_Adapter sa ((ACE_Sig_Handler_Ex) ACE_Reactor::end_event_loop);
+
+ ACE_Sig_Set sig_set;
+ sig_set.sig_add (SIGINT);
+ sig_set.sig_add (SIGQUIT);
+
+ // Register ourselves to receive signals so we can shut down
+ // gracefully.
+ if (ACE_Reactor::instance ()->register_handler (sig_set,
+ &sa) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"), ACE_TEXT ("register_handler")),
+ -1);
+
+ // This makes the README demo even easier (for sighup).
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("pid = %d\n"),
+ ACE_OS::getpid ()));
+
+ // Run forever, performing the configured services until we are shut
+ // down by a SIGINT/SIGQUIT signal.
+
+ // We use this version of the event loop so that reconfigurations
+ // are triggered properly.
+ ACE_Reactor::run_event_loop ();
+
+ return 0;
+}
diff --git a/ACE/examples/Service_Configurator/IPC-tests/server/svc.conf b/ACE/examples/Service_Configurator/IPC-tests/server/svc.conf
new file mode 100644
index 00000000000..6f4e70a3ca5
--- /dev/null
+++ b/ACE/examples/Service_Configurator/IPC-tests/server/svc.conf
@@ -0,0 +1,19 @@
+# To configure different services, simply uncomment the appropriate lines in this file!
+static ACE_Service_Manager "-d -p 3911"
+dynamic Remote_Brdcast Service_Object * ./IPC_Tests_Server:remote_broadcast "-p 10001"
+dynamic Remote_Stream Service_Object * ./IPC_Tests_Server:remote_stream "-p 20002"
+dynamic Remote_Dgram Service_Object * ./IPC_Tests_Server:remote_dgram "-p 15001"
+dynamic Timer_1 Service_Object * ./IPC_Tests_Server:timer_1 "-d 5 -i 1 -a 100"
+dynamic Local_Stream Service_Object * ./IPC_Tests_Server:local_stream "-r /tmp/foo_stream"
+dynamic Local_Pipe Service_Object * ./IPC_Tests_Server:local_pipe "-r /tmp/foo_pipe"
+dynamic Local_Fifo Service_Object * ./IPC_Tests_Server:local_fifo "-r /tmp/foo_fifo"
+dynamic Local_Dgram Service_Object * ./IPC_Tests_Server:local_dgram "-r /tmp/foo_dgram"
+dynamic Local_CODgram Service_Object * ./IPC_Tests_Server:local_codgram "-r /tmp/foo_codgram"
+dynamic Local_Spipe Service_Object * ./IPC_Tests_Server:local_spipe "-r /tmp/foo_spipe"
+dynamic Remote_Thr_Stream Service_Object * ./IPC_Tests_Server:remote_thr_stream "-p 10001"
+#suspend Remote_Stream
+#resume Local_SPIPE
+#resume Remote_Stream
+#remove Remote_Stream
+#remove Local_Stream
+
diff --git a/ACE/examples/Service_Configurator/Makefile.am b/ACE/examples/Service_Configurator/Makefile.am
new file mode 100644
index 00000000000..1b78bb27757
--- /dev/null
+++ b/ACE/examples/Service_Configurator/Makefile.am
@@ -0,0 +1,14 @@
+## Process this file with automake to create Makefile.in
+##
+## $Id$
+##
+## This file was generated by MPC. Any changes made directly to
+## this file will be lost the next time it is generated.
+##
+## MPC Command:
+## /acebuilds/ACE_wrappers-repository/bin/mwc.pl -include /acebuilds/MPC/config -include /acebuilds/MPC/templates -feature_file /acebuilds/ACE_wrappers-repository/local.features -noreldefs -type automake -exclude build,Kokyu
+
+SUBDIRS = \
+ IPC-tests \
+ Misc
+
diff --git a/ACE/examples/Service_Configurator/Misc/.cvsignore b/ACE/examples/Service_Configurator/Misc/.cvsignore
new file mode 100644
index 00000000000..ba2906d0666
--- /dev/null
+++ b/ACE/examples/Service_Configurator/Misc/.cvsignore
@@ -0,0 +1 @@
+main
diff --git a/ACE/examples/Service_Configurator/Misc/Makefile.am b/ACE/examples/Service_Configurator/Misc/Makefile.am
new file mode 100644
index 00000000000..f0de4232add
--- /dev/null
+++ b/ACE/examples/Service_Configurator/Misc/Makefile.am
@@ -0,0 +1,50 @@
+## Process this file with automake to create Makefile.in
+##
+## $Id$
+##
+## This file was generated by MPC. Any changes made directly to
+## this file will be lost the next time it is generated.
+##
+## MPC Command:
+## /acebuilds/ACE_wrappers-repository/bin/mwc.pl -include /acebuilds/MPC/config -include /acebuilds/MPC/templates -feature_file /acebuilds/ACE_wrappers-repository/local.features -noreldefs -type automake -exclude build,Kokyu
+
+ACE_BUILDDIR = $(top_builddir)
+ACE_ROOT = $(top_srcdir)
+
+## Makefile.Service_Configurator_Misc_Timer.am
+
+noinst_LTLIBRARIES = libtimer.la
+
+libtimer_la_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR) \
+ -DACE_BUILD_SVC_DLL
+
+libtimer_la_SOURCES = \
+ Timer_Service.cpp
+
+noinst_HEADERS = \
+ Timer_Service.h
+
+## Makefile.Service_Configurator_Misc_Main.am
+noinst_PROGRAMS = main
+
+main_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+main_SOURCES = \
+ main.cpp \
+ Timer_Service.h
+
+main_LDADD = \
+ libtimer.la \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Clean up template repositories, etc.
+clean-local:
+ -rm -f *~ *.bak *.rpo *.sym lib*.*_pure_* core core.*
+ -rm -f gcctemp.c gcctemp so_locations *.ics
+ -rm -rf cxx_repository ptrepository ti_files
+ -rm -rf templateregistry ir.out
+ -rm -rf ptrepository SunWS_cache Templates.DB
diff --git a/ACE/examples/Service_Configurator/Misc/README b/ACE/examples/Service_Configurator/Misc/README
new file mode 100644
index 00000000000..c3b22759926
--- /dev/null
+++ b/ACE/examples/Service_Configurator/Misc/README
@@ -0,0 +1,23 @@
+This directory contains an example that illustrates how the ACE
+Service Configurator can configure static and dynamic services, both
+from the command-line and from a svc.config file. We define several
+instances, i.e., Timer_Service_1 and Timer_Service_2 of the SAME
+service just to exercise different configuration options. A "real"
+application would usually define different services.
+
+Windows CE:
+-----------
+
+When using Windows CE (WCE) emulator, make sure that you use the
+following command to copy the svc.conf files into the top-level
+directory in CE emulator.
+
+ empfile -c svc.conf1 wce:\svc.conf1
+ empfile -c svc.conf2 wce:\svc.conf2
+
+The command "empfile" moves the files to emulator's root directory and
+resigters the files with CE emulator's object store.
+
+Also make sure you type in at least one argument (which is argv[0],)
+when the program dialog box requests you to key in the program
+arguments. Otherwise, the program won't run at all.
diff --git a/ACE/examples/Service_Configurator/Misc/Service_Configurator_Misc.mpc b/ACE/examples/Service_Configurator/Misc/Service_Configurator_Misc.mpc
new file mode 100644
index 00000000000..9c9744fd601
--- /dev/null
+++ b/ACE/examples/Service_Configurator/Misc/Service_Configurator_Misc.mpc
@@ -0,0 +1,18 @@
+// -*- MPC -*-
+// $Id$
+
+project(*Timer) : acelib {
+ sharedname = timer
+ dynamicflags += ACE_BUILD_SVC_DLL
+ Source_Files {
+ Timer_Service.cpp
+ }
+}
+project(*Main) : aceexe {
+ exename = main
+ after += Service_Configurator_Misc_Timer
+ libs += timer
+ Source_Files {
+ main.cpp
+ }
+}
diff --git a/ACE/examples/Service_Configurator/Misc/Timer_Service.cpp b/ACE/examples/Service_Configurator/Misc/Timer_Service.cpp
new file mode 100644
index 00000000000..82ace8f657c
--- /dev/null
+++ b/ACE/examples/Service_Configurator/Misc/Timer_Service.cpp
@@ -0,0 +1,135 @@
+// $Id$
+
+#include "ace/OS_NS_string.h"
+#include "Timer_Service.h"
+#include "ace/Log_Msg.h"
+
+ACE_RCSID(Misc, Timer_Service, "$Id$")
+
+Timer_Service_1::Timer_Service_1 (void)
+{
+ ACE_OS::strcpy (this->name_,
+ ACE_TEXT ("Timer_Service_1"));
+}
+
+int
+Timer_Service_1::init (int argc, ACE_TCHAR *argv[])
+{
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("in Timer_Service::init, argv[0] = %s, argc == %d\n"),
+ argv[0], argc));
+
+ // Printout the <argv> values for sanity's sake.
+ for (int i = 0; i < argc; i++)
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("argv[%d] = %s\n"),
+ i, argv[i]));
+
+ int interval = Timer_Service_1::TIMEOUT;
+
+ if (argc > 1)
+ {
+ // If the second argument exists use this as the interval for
+ // the periodic timer. Otherwise, go off every TIMEOUT seconds.
+
+ interval = ACE_OS::atoi (argv[1]);
+
+ if (interval == 0)
+ interval = Timer_Service_1::TIMEOUT;
+ }
+
+ if (argc > 2)
+ {
+ // If the third argument exists use it to control the maximum
+ // number of timeouts.
+ this->max_timeouts_ = ACE_OS::atoi (argv[2]);
+
+ if (this->max_timeouts_ == 0)
+ this->max_timeouts_ = Timer_Service_1::MAX_TIMEOUTS;
+ }
+
+ this->cur_timeouts_ = 0;
+
+ // If the fourth argument exists take this as an indication to
+ // enable tracing.
+#if defined (ACE_HAS_TRACE)
+ if (argc > 3)
+ ACE_Trace::start_tracing ();
+ else
+ ACE_Trace::stop_tracing ();
+#endif /* ACE_HAS_TRACE */
+
+ // Register the timer to go off in 1 second, and then to go off
+ // every <interval> seconds.
+ if (ACE_Reactor::instance ()->schedule_timer
+ (this,
+ 0,
+ ACE_Time_Value (1),
+ ACE_Time_Value (interval)) == -1)
+ return -1;
+ else
+ return 0;
+}
+
+int
+Timer_Service_1::handle_timeout (const ACE_Time_Value &tv,
+ const void *)
+{
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("(%x) in %s::handle_timeout sec = %d, usec = %d")
+ ACE_TEXT (" cur_timeouts = %d, max_timeouts = %d\n"),
+ this,
+ this->name_,
+ tv.sec (),
+ tv.usec (),
+ this->cur_timeouts_,
+ this->max_timeouts_));
+
+ this->cur_timeouts_++;
+
+ if (this->cur_timeouts_ == this->max_timeouts_)
+ // Shutdown the test.
+ return -1;
+ else
+ return 0;
+}
+
+int
+Timer_Service_1::handle_close (ACE_HANDLE,
+ ACE_Reactor_Mask)
+{
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("closing down the timer test\n")));
+
+ // Remove ourselves from the timer queue.
+ ACE_Reactor::instance ()->cancel_timer (this);
+
+ ACE_Reactor::end_event_loop();
+ return 0;
+}
+
+Timer_Service_2::Timer_Service_2 (void)
+{
+ ACE_OS::strcpy (this->name_,
+ ACE_TEXT ("Timer_Service_2"));
+}
+
+Timer_Service_3::Timer_Service_3 (void)
+{
+ ACE_OS::strcpy (this->name_,
+ ACE_TEXT ("Timer_Service_3"));
+}
+
+// Define the object that describes the service.
+ACE_STATIC_SVC_DEFINE (Timer_Service_1,
+ ACE_TEXT ("Timer_Service_1"),
+ ACE_SVC_OBJ_T,
+ &ACE_SVC_NAME (Timer_Service_1),
+ ACE_Service_Type::DELETE_THIS | ACE_Service_Type::DELETE_OBJ,
+ 0)
+
+// The following are "Factories" used by the <ACE_Service_Config> and
+// svc.conf file to dynamically initialize the state of the Timer
+// Services.
+ACE_SVC_FACTORY_DEFINE (Timer_Service_1)
+ACE_SVC_FACTORY_DEFINE (Timer_Service_2)
+ACE_SVC_FACTORY_DEFINE (Timer_Service_3)
diff --git a/ACE/examples/Service_Configurator/Misc/Timer_Service.h b/ACE/examples/Service_Configurator/Misc/Timer_Service.h
new file mode 100644
index 00000000000..01aa77b7317
--- /dev/null
+++ b/ACE/examples/Service_Configurator/Misc/Timer_Service.h
@@ -0,0 +1,71 @@
+// -*- C++ -*-
+//
+// $Id$
+
+#include "ace/svc_export.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/Service_Config.h"
+#include "ace/Reactor.h"
+#include "ace/Service_Object.h"
+
+
+class ACE_Svc_Export Timer_Service_1 : public ACE_Service_Object
+{
+ // = TITLE
+ // Demonstrates a simple timer service that can be configured
+ // statically.
+public:
+ Timer_Service_1 (void);
+ // Default constructor.
+
+ virtual int init (int argc, ACE_TCHAR *argv[]);
+ // Initialization hook.
+
+ virtual int handle_timeout (const ACE_Time_Value &,
+ const void *);
+ // Timeout hook.
+
+ virtual int handle_close (ACE_HANDLE, ACE_Reactor_Mask);
+ // Close hook.
+
+protected:
+ ACE_TCHAR name_[BUFSIZ];
+ // Keep track of which service this is!
+
+private:
+ enum
+ {
+ TIMEOUT = 4, // Wait 4 seconds between timeouts
+ MAX_TIMEOUTS = 10 // Don't timeout for more than 10 times.
+ };
+
+ int max_timeouts_;
+ // Maximum number of timeouts before shutting down the test.
+
+ int cur_timeouts_;
+ // Current number of timeouts.
+};
+
+class ACE_Svc_Export Timer_Service_2 : public Timer_Service_1
+{
+public:
+ Timer_Service_2 (void);
+ // Default constructor.
+};
+
+class ACE_Svc_Export Timer_Service_3 : public Timer_Service_1
+{
+public:
+ Timer_Service_3 (void);
+ // Default constructor.
+};
+
+// Declare both static and dynamic services.
+ACE_STATIC_SVC_DECLARE_EXPORT (ACE_Svc, Timer_Service_1)
+ACE_SVC_FACTORY_DECLARE (Timer_Service_1)
+ACE_SVC_FACTORY_DECLARE (Timer_Service_2)
+ACE_SVC_FACTORY_DECLARE (Timer_Service_3)
diff --git a/ACE/examples/Service_Configurator/Misc/main.cpp b/ACE/examples/Service_Configurator/Misc/main.cpp
new file mode 100644
index 00000000000..a7ff6c9da26
--- /dev/null
+++ b/ACE/examples/Service_Configurator/Misc/main.cpp
@@ -0,0 +1,80 @@
+// $Id$
+
+// ============================================================================
+//
+// = LIBRARY
+// examples/Service_Configurator/Misc
+//
+// = FILENAME
+// main.cpp
+//
+// = DESCRIPTION
+// This directory contains an example that illustrates how the ACE
+// Service Configurator can configure static and dynamic services,
+// both from the command-line and from a svc.config file.
+//
+// = AUTHOR
+// Doug Schmidt <schmidt@cs.wustl.edu>
+//
+// ============================================================================
+
+#include "ace/OS_main.h"
+#include "ace/Service_Config.h"
+#include "ace/ARGV.h"
+#include "ace/Log_Msg.h"
+#include "Timer_Service.h"
+
+ACE_RCSID(Misc, main, "$Id$")
+
+// Create an object that will insert the <Timer_Service> into the list
+// of statically linked services that the <ACE_Service_Config> will
+// process at run-time.
+ACE_STATIC_SVC_REQUIRE (Timer_Service_1)
+
+int
+ACE_TMAIN (int, ACE_TCHAR *argv[])
+{
+ // Set up an argument vector that we can add entries to!
+ ACE_ARGV args;
+
+ // Manufacture a "fake" svc.conf entry to demonstrate the -S option
+ // that allows us to pass these entries via the "command-line"
+ // rather than the svc.conf file.
+ args.add (argv[0]);
+ args.add (ACE_TEXT ("-y"));
+ args.add (ACE_TEXT ("-d"));
+ args.add (ACE_TEXT ("-S"));
+ args.add (ACE_TEXT ("\"static Timer_Service_1 'timer 1 10 $TRACE'\""));
+ args.add (ACE_TEXT ("-S"));
+ args.add (ACE_TEXT ("\"dynamic Timer_Service_2 Service_Object * ./Timer:_make_Timer_Service_2() 'timer 2 10 $TRACE'\""));
+ // Test the -f option!
+ args.add (ACE_TEXT ("-fsvc.conf1"));
+ args.add (ACE_TEXT ("-fsvc.conf2"));
+
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("argc = %d\n"),
+ args.argc ()));
+
+ // Print the contents of the combined <ACE_ARGV>.
+ for (int i = 0; i < args.argc (); i++)
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("(%d) %s\n"),
+ i,
+ args.argv ()[i]));
+
+ int result = ACE_Service_Config::open (args.argc (),
+ args.argv (),
+ ACE_DEFAULT_LOGGER_KEY,
+ 0);
+ if (result != 0)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("open")),
+ 1);
+
+ // Run forever, performing the configured services until we
+ // shutdown.
+
+ ACE_Reactor::run_event_loop ();
+ return 0;
+}
diff --git a/ACE/examples/Service_Configurator/Misc/svc.conf1 b/ACE/examples/Service_Configurator/Misc/svc.conf1
new file mode 100644
index 00000000000..d0f552caa6e
--- /dev/null
+++ b/ACE/examples/Service_Configurator/Misc/svc.conf1
@@ -0,0 +1,8 @@
+# Dynamically configure the Timer_Service into the application process
+# and pass in up to 4 arguments. The final 3 arguments are retrieved
+# from environment variables, so they can be set by changing your
+# environment before running the main program. If you don't have
+# these variables set they are ignored.
+dynamic Timer_Service_3 Service_Object *
+ ./Timer:_make_Timer_Service_3()
+ "timer $INTERVAL $MAX_TIMEOUTS $TRACE"
diff --git a/ACE/examples/Service_Configurator/Misc/svc.conf2 b/ACE/examples/Service_Configurator/Misc/svc.conf2
new file mode 100644
index 00000000000..1bef63e8d48
--- /dev/null
+++ b/ACE/examples/Service_Configurator/Misc/svc.conf2
@@ -0,0 +1,8 @@
+# Statically configure the Timer_Service, which must have been linked
+# statically into the application process. Up to 4 arguments are
+# passed in. The final 3 arguments are retrieved from environment
+# variables, so they can be set by changing your environment before
+# running the main program. If you don't have these variables set
+# they are ignored.
+static Timer_Service_1
+ "timer $INTERVAL $MAX_TIMEOUTS $TRACE"
diff --git a/ACE/examples/Shared_Malloc/.cvsignore b/ACE/examples/Shared_Malloc/.cvsignore
new file mode 100644
index 00000000000..c5ad2e56e0e
--- /dev/null
+++ b/ACE/examples/Shared_Malloc/.cvsignore
@@ -0,0 +1,4 @@
+malloc
+multiple
+persistence
+posind
diff --git a/ACE/examples/Shared_Malloc/Makefile.am b/ACE/examples/Shared_Malloc/Makefile.am
new file mode 100644
index 00000000000..baccb0359e0
--- /dev/null
+++ b/ACE/examples/Shared_Malloc/Makefile.am
@@ -0,0 +1,106 @@
+## Process this file with automake to create Makefile.in
+##
+## $Id$
+##
+## This file was generated by MPC. Any changes made directly to
+## this file will be lost the next time it is generated.
+##
+## MPC Command:
+## /acebuilds/ACE_wrappers-repository/bin/mwc.pl -include /acebuilds/MPC/config -include /acebuilds/MPC/templates -feature_file /acebuilds/ACE_wrappers-repository/local.features -noreldefs -type automake -exclude build,Kokyu
+
+ACE_BUILDDIR = $(top_builddir)
+ACE_ROOT = $(top_srcdir)
+
+noinst_PROGRAMS =
+
+## Makefile.Shared_Malloc.am
+
+if !BUILD_ACE_FOR_TAO
+noinst_PROGRAMS += malloc
+
+malloc_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+malloc_SOURCES = \
+ Malloc.cpp \
+ Options.cpp \
+ test_malloc.cpp \
+ Malloc.h \
+ Options.h
+
+malloc_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+endif !BUILD_ACE_FOR_TAO
+
+## Makefile.Shared_Malloc_Multiple.am
+
+if !BUILD_ACE_FOR_TAO
+noinst_PROGRAMS += multiple
+
+multiple_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+multiple_SOURCES = \
+ Malloc.cpp \
+ Options.cpp \
+ test_multiple_mallocs.cpp \
+ Malloc.h \
+ Options.h
+
+multiple_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+endif !BUILD_ACE_FOR_TAO
+
+## Makefile.Shared_Malloc_Persistence.am
+
+if !BUILD_ACE_FOR_TAO
+noinst_PROGRAMS += persistence
+
+persistence_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+persistence_SOURCES = \
+ test_persistence.cpp \
+ Malloc.h \
+ Options.h \
+ test_position_independent_malloc.h
+
+persistence_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+endif !BUILD_ACE_FOR_TAO
+
+## Makefile.Shared_Malloc_Posind.am
+
+if !BUILD_ACE_FOR_TAO
+noinst_PROGRAMS += posind
+
+posind_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+posind_SOURCES = \
+ Malloc.cpp \
+ Options.cpp \
+ test_position_independent_malloc.cpp \
+ Malloc.h \
+ Options.h \
+ test_position_independent_malloc.h
+
+posind_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+endif !BUILD_ACE_FOR_TAO
+
+## Clean up template repositories, etc.
+clean-local:
+ -rm -f *~ *.bak *.rpo *.sym lib*.*_pure_* core core.*
+ -rm -f gcctemp.c gcctemp so_locations *.ics
+ -rm -rf cxx_repository ptrepository ti_files
+ -rm -rf templateregistry ir.out
+ -rm -rf ptrepository SunWS_cache Templates.DB
diff --git a/ACE/examples/Shared_Malloc/Malloc.cpp b/ACE/examples/Shared_Malloc/Malloc.cpp
new file mode 100644
index 00000000000..4499d9fa11b
--- /dev/null
+++ b/ACE/examples/Shared_Malloc/Malloc.cpp
@@ -0,0 +1,69 @@
+// $Id$
+
+#include "Options.h"
+#include "Malloc.h"
+#include "ace/MMAP_Memory_Pool.h"
+#include "ace/Local_Memory_Pool.h"
+
+#ifndef ACE_LACKS_SYSV_SHMEM
+# include "ace/Shared_Memory_Pool.h"
+#endif /* !ACE_LACKS_SYSV_SHMEM */
+
+#ifndef ACE_LACKS_SBRK
+# include "ace/Sbrk_Memory_Pool.h"
+#endif /* !ACE_LACKS_SBRK */
+
+#include "ace/Process_Mutex.h"
+#include "ace/Malloc_T.h"
+
+ACE_RCSID(Shared_Malloc, Malloc, "$Id$")
+
+// Strategic typedefs for memory allocation.
+
+typedef ACE_Malloc <ACE_LOCAL_MEMORY_POOL, ACE_SYNCH_MUTEX> L_ALLOCATOR;
+typedef ACE_Malloc <ACE_MMAP_MEMORY_POOL, ACE_Process_Mutex> M_ALLOCATOR;
+
+#if defined (ACE_LACKS_SYSV_SHMEM)
+typedef ACE_Malloc <ACE_MMAP_MEMORY_POOL, ACE_SYNCH_MUTEX> SP_ALLOCATOR;
+typedef ACE_Malloc <ACE_MMAP_MEMORY_POOL, ACE_SYNCH_MUTEX> ST_ALLOCATOR;
+#else
+typedef ACE_Malloc <ACE_SHARED_MEMORY_POOL, ACE_Process_Mutex> SP_ALLOCATOR;
+typedef ACE_Malloc <ACE_SHARED_MEMORY_POOL, ACE_SYNCH_MUTEX> ST_ALLOCATOR;
+#endif /* ACE_LACKS_SYSV_SHMEM */
+
+#if defined (ACE_LACKS_SBRK)
+typedef ACE_Malloc <ACE_LOCAL_MEMORY_POOL, ACE_SYNCH_MUTEX> SB_ALLOCATOR;
+#else
+typedef ACE_Malloc <ACE_SBRK_MEMORY_POOL, ACE_SYNCH_MUTEX> SB_ALLOCATOR;
+#endif /* ACE_LACKS_SBRK */
+
+// Singleton
+ACE_Allocator *Malloc::instance_ = 0;
+
+// This is a factory that decides what type of allocator to create.
+
+ACE_Allocator *
+Malloc::instance (void)
+{
+ if (Malloc::instance_ == 0)
+ {
+ if (Options::instance ()->child ())
+ Malloc::instance_ = new ACE_Allocator_Adapter<M_ALLOCATOR>;
+ else if (Options::instance ()->spawn_threads ())
+ {
+ if (Options::instance ()->use_sbrk ())
+ Malloc::instance_ = new ACE_Allocator_Adapter<SB_ALLOCATOR>;
+ else if (Options::instance ()->use_shmem ())
+ Malloc::instance_ = new ACE_Allocator_Adapter<ST_ALLOCATOR>;
+ else
+ Malloc::instance_ = new ACE_Allocator_Adapter<L_ALLOCATOR>;
+ }
+ else if (Options::instance ()->use_mmap ())
+ Malloc::instance_ = new ACE_Allocator_Adapter<M_ALLOCATOR>;
+ else // Use Shared_Memory_Pool.
+ Malloc::instance_ = new ACE_Allocator_Adapter<SP_ALLOCATOR>;
+ }
+
+ return Malloc::instance_;
+}
+
diff --git a/ACE/examples/Shared_Malloc/Malloc.h b/ACE/examples/Shared_Malloc/Malloc.h
new file mode 100644
index 00000000000..c88cead8bfb
--- /dev/null
+++ b/ACE/examples/Shared_Malloc/Malloc.h
@@ -0,0 +1,33 @@
+/* -*- C++ -*- */
+// $Id$
+
+#ifndef MY_MALLOC_H
+#define MY_MALLOC_H
+
+#include "ace/config-all.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+class ACE_Allocator;
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+class Malloc
+ // = TITLE
+ // Allocator Singleton.
+{
+public:
+ static ACE_Allocator *instance (void);
+ // Returns static instance.
+
+private:
+ Malloc (void);
+ // Ensure Singleton.
+
+ static ACE_Allocator *instance_;
+ // Malloc Singleton.
+};
+
+#endif /* MY_MALLOC_H */
diff --git a/ACE/examples/Shared_Malloc/Options.cpp b/ACE/examples/Shared_Malloc/Options.cpp
new file mode 100644
index 00000000000..6716fa66c31
--- /dev/null
+++ b/ACE/examples/Shared_Malloc/Options.cpp
@@ -0,0 +1,201 @@
+// $Id$
+
+#include "ace/Get_Opt.h"
+#include "Options.h"
+#include "ace/Log_Msg.h"
+#include "ace/OS_NS_stdlib.h"
+#include "ace/OS_NS_string.h"
+
+ACE_RCSID (Shared_Malloc,
+ Options,
+ "$Id$")
+
+// Static Singleton instance.
+Options *Options::instance_ = 0;
+
+Options *
+Options::instance (void)
+{
+ if (Options::instance_ == 0)
+ Options::instance_ = new Options ();
+
+ return Options::instance_;
+}
+
+const char *
+Options::program_name (void)
+{
+ return this->program_name_;
+}
+
+const char *
+Options::slave_name (void)
+{
+ return this->slave_name_;
+}
+
+int
+Options::debug (void)
+{
+ return this->debug_;
+}
+
+int
+Options::exec_slave (void)
+{
+ return this->exec_slave_;
+}
+
+size_t
+Options::iteration_count (void)
+{
+ return this->iteration_count_;
+}
+
+int
+Options::use_sbrk (void)
+{
+ return this->use_sbrk_;
+}
+
+size_t
+Options::max_msg_size (void)
+{
+ return this->max_msg_size_;
+}
+
+size_t
+Options::spawn_count (void)
+{
+ return this->spawn_count_;
+}
+
+int
+Options::spawn_threads (void)
+{
+ return this->spawn_threads_;
+}
+
+int
+Options::use_mmap (void)
+{
+ return this->use_mmap_;
+}
+
+int
+Options::use_shmem (void)
+{
+ return this->use_shmem_;
+}
+
+int
+Options::child (void)
+{
+ return this->child_;
+}
+
+// Explain usage and exit.
+
+void
+Options::print_usage_and_die (void)
+{
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("usage: %n")
+ ACE_TEXT ("\n[-d] (run in debugging mode)\n")
+ ACE_TEXT ("[-e] (use exec(2) in addition to fork(2))\n")
+ ACE_TEXT ("[-l] (use C++ new operator rather than sbrk(2)\n")
+ ACE_TEXT ("[-L max_msg_size]\n")
+ ACE_TEXT ("[-m] (use mmap rather than SysV shared memory)\n")
+ ACE_TEXT ("[-p] (use processes rather than threads)\n")
+ ACE_TEXT ("[-s] (use SysV shared memory rather than mmap)\n")
+ ACE_TEXT ("[-t number of threads or processes to spawn]\n")
+ ACE_TEXT ("[-T] (enable tracking)\n")
+ ACE_TEXT ("[-n iteration_count]\n")));
+ ACE_OS::exit (1);
+ /* NOTREACHED */
+}
+
+Options::Options (void)
+ : debug_ (0),
+ exec_slave_ (0),
+ iteration_count_ (100),
+ use_sbrk_ (0),
+ use_shmem_ (0),
+ max_msg_size_ (127),
+ spawn_count_ (1),
+ spawn_threads_ (1),
+ use_mmap_ (0),
+ child_ (0)
+{
+ ACE_OS::strcpy (this->slave_name_, "slave");
+}
+
+void
+Options::parse_args (int argc, ACE_TCHAR *argv[])
+{
+ ACE_Get_Opt get_opt (argc, argv, ACE_TEXT ("dehlL:mn:pst:T"));
+
+ ACE_OS::strcpy (this->program_name_, ACE_TEXT_ALWAYS_CHAR (argv[0]));
+ ACE_LOG_MSG->open (argv[0]);
+
+ // Put in a special-case check for child process.
+ if (ACE_OS::strcmp (this->program_name_, slave_name_) == 0)
+ {
+ this->child_ = 1;
+ this->use_mmap_ = 1;
+ }
+
+ for (int c;
+ (c = get_opt ()) != -1;
+ )
+ {
+ switch (c)
+ {
+ case 'd':
+ this->debug_ = 1;
+ break;
+ case 'e':
+ this->exec_slave_ = 1;
+ break;
+ case 'h':
+ this->print_usage_and_die ();
+ /* NOTREACHED */
+ break;
+ case 'l':
+ this->use_sbrk_ = 0;
+ break;
+ case 'L':
+ this->max_msg_size_ = ACE_OS::atoi (get_opt.opt_arg ());
+ break;
+ case 'm':
+ this->use_mmap_ = 1;
+ break;
+ case 'n':
+ this->iteration_count_ = ACE_OS::atoi (get_opt.opt_arg ());
+ break;
+ case 'p': // Spawn processes rather than threads
+ this->spawn_threads_ = 0;
+ break;
+ case 's':
+ // Use System V shared memory...
+ this->use_shmem_ = 1;
+ break;
+ case 't':
+ this->spawn_count_ = ACE_OS::atoi (get_opt.opt_arg ());
+ break;
+ case 'T':
+#if defined (ACE_HAS_TRACE)
+ ACE_Trace::start_tracing ();
+#endif /* ACE_HAS_TRACE */
+ break;
+ default:
+ this->print_usage_and_die ();
+ /* NOTREACHED */
+ break;
+ }
+ }
+
+ // Switch to using MMAP when the -p and -e options are enabled.
+ if (this->exec_slave_ == 1 && this->spawn_threads_ == 0)
+ this->use_mmap_ = 1;
+}
diff --git a/ACE/examples/Shared_Malloc/Options.h b/ACE/examples/Shared_Malloc/Options.h
new file mode 100644
index 00000000000..67956d80cc3
--- /dev/null
+++ b/ACE/examples/Shared_Malloc/Options.h
@@ -0,0 +1,86 @@
+/* -*- C++ -*- */
+// $Id$
+
+#ifndef _OPTIONS
+#define _OPTIONS
+
+#include "ace/os_include/os_stddef.h"
+#include "ace/os_include/os_limits.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+class Options
+ // = TITLE
+ // Options Singleton.
+{
+public:
+ static Options *instance (void);
+ // Return Singleton.
+
+ void parse_args (int argc, ACE_TCHAR *argv[]);
+ // Parse the arguments.
+
+ // = Accessor methods.
+ const char *program_name (void);
+ const char *slave_name (void);
+ int debug (void);
+ int exec_slave (void);
+ size_t iteration_count (void);
+ int use_sbrk (void);
+ int use_shmem (void);
+ size_t max_msg_size (void);
+ size_t spawn_count (void);
+ int spawn_threads (void);
+ int use_mmap (void);
+ int child (void);
+
+private:
+ Options (void);
+ // Ensure Singleton.
+
+ static Options *instance_;
+ // Singleton.
+
+ void print_usage_and_die (void);
+ // Explain usage and exit.
+
+ char program_name_[MAXPATHLEN];
+ // Name of the program.
+
+ char slave_name_[MAXPATHLEN];
+ // Name of slave process.
+
+ int debug_;
+ // Flag to indicate if we are debugging.
+
+ int exec_slave_;
+ // Flag to indicate if we should exec after forking.
+
+ size_t iteration_count_;
+ // Number of iterations to call malloc_recurse().
+
+ int use_sbrk_;
+ // Should we use sbrk(2)?
+
+ int use_shmem_;
+ // Should we use Shared Memory?
+
+ size_t max_msg_size_;
+ // Maximum number of bytes to malloc.
+
+ size_t spawn_count_;
+ // Number of threads.
+
+ int spawn_threads_;
+ // Spawn threads vs. processes.
+
+ int use_mmap_;
+ // Use mmap() as the backing store.
+
+ int child_;
+ // We're a child process.
+};
+
+#endif /* _OPTIONS */
diff --git a/ACE/examples/Shared_Malloc/Shared_Malloc.mpc b/ACE/examples/Shared_Malloc/Shared_Malloc.mpc
new file mode 100644
index 00000000000..42753246815
--- /dev/null
+++ b/ACE/examples/Shared_Malloc/Shared_Malloc.mpc
@@ -0,0 +1,37 @@
+// -*- MPC -*-
+// $Id$
+
+project : aceexe {
+ avoids += ace_for_tao
+ exename = malloc
+ Source_Files {
+ Malloc.cpp
+ Options.cpp
+ test_malloc.cpp
+ }
+}
+project(*multiple) : aceexe {
+ avoids += ace_for_tao
+ exename = multiple
+ Source_Files {
+ Malloc.cpp
+ Options.cpp
+ test_multiple_mallocs.cpp
+ }
+}
+project(*persistence) : aceexe {
+ avoids += ace_for_tao
+ exename = persistence
+ Source_Files {
+ test_persistence.cpp
+ }
+}
+project(*posind) : aceexe {
+ avoids += ace_for_tao
+ exename = posind
+ Source_Files {
+ Malloc.cpp
+ Options.cpp
+ test_position_independent_malloc.cpp
+ }
+}
diff --git a/ACE/examples/Shared_Malloc/test_malloc.cpp b/ACE/examples/Shared_Malloc/test_malloc.cpp
new file mode 100644
index 00000000000..b6143aa989c
--- /dev/null
+++ b/ACE/examples/Shared_Malloc/test_malloc.cpp
@@ -0,0 +1,228 @@
+// $Id$
+
+// This program tests out all the various ACE_Malloc combinations and
+// the ACE_Allocator_Adapter.
+
+#include "ace/Thread.h"
+#include "ace/Thread_Manager.h"
+#include "ace/Malloc.h"
+#include "ace/Signal.h"
+#include "ace/OS_NS_stdio.h"
+#include "ace/OS_NS_string.h"
+#include "ace/OS_NS_sys_wait.h"
+#include "ace/OS_NS_unistd.h"
+#include "Malloc.h"
+#include "Options.h"
+
+ACE_RCSID(Shared_Malloc, test_malloc, "$Id$")
+
+static int
+gen_size (void)
+{
+#if defined (ACE_HAS_THREADS)
+ ACE_RANDR_TYPE seed = static_cast<ACE_RANDR_TYPE> (reinterpret_cast<unsigned long> (&seed));
+ return (ACE_OS::rand_r (seed) % Options::instance ()->max_msg_size ()) + 1;
+#else
+ return (ACE_OS::rand () % Options::instance ()->max_msg_size ()) + 1;
+#endif /* ACE_HAS_THREADS */
+}
+
+// Recursively allocate and deallocate dynamic memory.
+
+static int
+malloc_recurse (int count)
+{
+ static char default_char = 0;
+
+ if (count <= 0)
+ {
+ if (Options::instance ()->debug ())
+ {
+ // Note that you'll need to #define ACE_HAS_MALLOC_STATS in
+ // the main ACE config.h file and remake ACE to enable this.
+ ACE_MALLOC_STATS (Malloc::instance ()->print_stats ());
+ }
+ }
+ else
+ {
+ int alloc_size = gen_size ();
+ void *ptr = Malloc::instance ()->malloc (alloc_size);
+
+ if (ptr == 0)
+ ACE_ERROR ((LM_ERROR,
+ "(%P|%t) *** malloc of size %d failed, %p\n%a",
+ "malloc",
+ alloc_size));
+ else
+ {
+ ACE_OS::memset (ptr, default_char++, alloc_size);
+
+ if (Options::instance ()->debug ())
+ ACE_DEBUG ((LM_INFO,
+ "(%P|%t) %u (alloc), size = %d\n",
+ ptr,
+ alloc_size));
+
+ // Call ourselves recursively
+ malloc_recurse (count - 1);
+
+ if (Options::instance ()->debug ())
+ ACE_DEBUG ((LM_INFO,
+ "(%P|%t) %u (free), size = %d\n",
+ ptr,
+ alloc_size));
+ Malloc::instance ()->free (ptr);
+ }
+ }
+
+ return 0;
+}
+
+#if defined (ACE_HAS_THREADS)
+static void *
+worker (void *arg)
+{
+ // Cast the arg to a long, first, because a pointer is the same
+ // size as a long on all current ACE platforms.
+ malloc_recurse ((int) (long) arg);
+
+ return 0;
+}
+#endif /* ACE_HAS_THREADS */
+
+// Create the appropriate type of process/thread.
+
+static void
+spawn (void)
+{
+ if (Options::instance ()->spawn_threads ())
+ {
+#if defined (ACE_HAS_THREADS)
+ if (ACE_Thread_Manager::instance ()->spawn (ACE_THR_FUNC (worker),
+ (void *) Options::instance ()->iteration_count (),
+ THR_BOUND) == -1)
+ ACE_ERROR ((LM_ERROR, "%p\n%a", "thread create failed"));
+#else
+ if (Options::instance ()->spawn_count () > 1)
+ ACE_ERROR ((LM_ERROR,
+ "only one thread may be run in a process on this platform\n%a",
+ 1));
+#endif /* ACE_HAS_THREADS */
+ }
+#if !defined (ACE_WIN32)
+ else if (ACE_OS::fork (ACE_TEXT_CHAR_TO_TCHAR (Options::instance ()->program_name ())) == 0)
+ {
+ if (Options::instance ()->exec_slave ())
+ {
+ char iterations[20];
+ char msg_size[20];
+
+ ACE_OS::sprintf (iterations, "%lu",
+ (unsigned long)
+ Options::instance ()->iteration_count ());
+ ACE_OS::sprintf (msg_size, "%lu",
+ (unsigned long)
+ Options::instance ()->max_msg_size ());
+ const char *cp = 0;
+
+ if (Options::instance ()->debug ())
+ cp = "-d";
+ else
+ cp = "";
+
+ const char *argv[] =
+ {
+ Options::instance ()->slave_name (),
+ "-p",
+ "-n",
+ iterations,
+ "-L",
+ msg_size,
+ cp,
+ 0
+ };
+
+ if (ACE_OS::execv (Options::instance ()->program_name (),
+ (char *const *) argv) == -1)
+ ACE_ERROR ((LM_ERROR, "%p\n", "exec failed"));
+ ACE_OS::_exit (1);
+ }
+ else
+ {
+ ACE_DEBUG ((LM_INFO,
+ "(%P|%t) about to recurse with iteration count = %d\n",
+ Options::instance ()->iteration_count ()));
+
+ malloc_recurse (Options::instance ()->iteration_count ());
+ Malloc::instance ()->remove ();
+ ACE_OS::exit (0);
+ }
+ }
+#endif /* ACE_WIN32 */
+}
+
+// Wait for all the child processes/threads to exit.
+
+static void
+wait_for_children (void)
+{
+ if (Options::instance ()->spawn_threads ())
+ {
+#if defined (ACE_HAS_THREADS)
+ // Wait for the threads to terminate.
+ ACE_Thread_Manager::instance ()->wait ();
+#else
+ malloc_recurse (Options::instance ()->iteration_count ());
+#endif /* ACE_HAS_THREADS */
+ }
+#if !defined (ACE_WIN32)
+ else
+ {
+ pid_t pid;
+
+ while ((pid = ACE_OS::wait (0)) != -1)
+ ACE_DEBUG ((LM_DEBUG, "(%P|%t) reaped pid = %d\n", pid));
+ }
+#endif /* ACE_WIN32 */
+}
+
+extern "C" void
+handler (int)
+{
+ Malloc::instance ()->remove ();
+ ACE_ERROR ((LM_ERROR, "(%P|%t) removed handler\n%a", 0));
+}
+
+int
+ACE_TMAIN (int argc, ACE_TCHAR *argv[])
+{
+ // Register a signal handler.
+ ACE_Sig_Action sa ((ACE_SignalHandler) handler, SIGINT);
+ ACE_UNUSED_ARG (sa);
+
+ Options::instance ()->parse_args (argc, argv);
+
+#if !defined (ACE_WIN32)
+ if (Options::instance ()->child ())
+ {
+ ACE_DEBUG ((LM_INFO,
+ "(%P|%t) about to recurse with iteration count = %d, debug = %d\n",
+ Options::instance ()->iteration_count ()));
+
+ // We've been forked...
+ malloc_recurse (Options::instance ()->iteration_count ());
+ Malloc::instance ()->remove ();
+ }
+ else
+#endif /* ACE_WIN32 */
+ {
+ for (size_t i = 0;
+ i < Options::instance ()->spawn_count ();
+ i++)
+ spawn ();
+
+ wait_for_children ();
+ Malloc::instance ()->remove ();
+ }
+ return 0;
+}
diff --git a/ACE/examples/Shared_Malloc/test_multiple_mallocs.cpp b/ACE/examples/Shared_Malloc/test_multiple_mallocs.cpp
new file mode 100644
index 00000000000..1638a762060
--- /dev/null
+++ b/ACE/examples/Shared_Malloc/test_multiple_mallocs.cpp
@@ -0,0 +1,125 @@
+// $Id$
+
+// Test the capability of <ACE_Malloc> to handle multiple mallocs
+// rooted at different base addresses.
+
+#include "ace/OS_NS_string.h"
+#include "ace/Malloc_T.h"
+#include "ace/MMAP_Memory_Pool.h"
+#include "ace/Auto_Ptr.h"
+#include "ace/Process_Mutex.h"
+
+ACE_RCSID(Shared_Malloc, test_multiple_mallocs, "$Id$")
+
+typedef ACE_Malloc <ACE_MMAP_MEMORY_POOL, ACE_Process_Mutex> TEST_MALLOC;
+
+#if (ACE_HAS_POSITION_INDEPENDENT_POINTERS == 1)
+// The Address for the shared memory mapped files defaults to wherever
+// the OS wants to map it.
+const void *REQUEST_BASE_ADDR = 0;
+const void *RESPONSE_BASE_ADDR = 0;
+#else
+// Default address for shared memory mapped files and SYSV shared
+// memory (defaults to 64 M).
+const void *REQUEST_BASE_ADDR = ((void *) (64 * 1024 * 1024));
+
+// Default address for shared memory mapped files and SYSV shared
+// memory (defaults to 64 M).
+const void *RESPONSE_BASE_ADDR = ((void *) (128 * 1024 * 1024));
+#endif /* ACE_HAS_POSITION_INDEPENDENT_POINTERS == 1 */
+
+static const char *request_string = "hello from request repository";
+static const char *response_string = "hello from response repository";
+
+int
+ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ ACE_MMAP_Memory_Pool_Options request_options (REQUEST_BASE_ADDR);
+
+ // Create an adapter version of an allocator.
+ ACE_Allocator_Adapter<TEST_MALLOC> *adapter_ptr = 0;
+ ACE_NEW_RETURN (adapter_ptr,
+ ACE_Allocator_Adapter<TEST_MALLOC> ("request_file",
+ "request_lock",
+ &request_options),
+ 1);
+
+ auto_ptr <ACE_Allocator_Adapter<TEST_MALLOC> > shmem_request (adapter_ptr);
+ ACE_MMAP_Memory_Pool_Options response_options (RESPONSE_BASE_ADDR);
+
+ TEST_MALLOC *ptr = 0;
+ // Create a non-adapter version of an allocator.
+ ACE_NEW_RETURN (ptr,
+ TEST_MALLOC (ACE_TEXT("response_file"),
+ ACE_TEXT("response_lock"),
+ &response_options),
+ 1);
+ auto_ptr <TEST_MALLOC> shmem_response (ptr);
+ void *data = 0;
+
+ // If we find "foo" then we're running the "second" time, so we must
+ // release the resources.
+ if (shmem_request->find ("foo",
+ data) == 0)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ "%s\n",
+ data));
+ shmem_request->remove ();
+ }
+
+ // This is the first time in, so we allocate the memory and bind it
+ // to the name "foo".
+ else
+ {
+ ACE_ALLOCATOR_RETURN (data,
+ shmem_request->malloc (ACE_OS::strlen (request_string) + 1),
+ 1);
+ ACE_OS::strcpy ((char *) data,
+ request_string);
+
+ if (shmem_request->bind ("foo",
+ data) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%p\n",
+ "bind"),
+ 1);
+ }
+ data = 0;
+
+ // If we find "foo" then we're running the "second" time, so we must
+ // release the resources.
+ if (shmem_response->find ("foo",
+ data) == 0)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ "%s\n",
+ data));
+ shmem_response->remove ();
+ ACE_DEBUG ((LM_DEBUG,
+ "all shared memory resources have been released\n"));
+ }
+
+ // This is the first time in, so we allocate the memory and bind it
+ // to the name "foo".
+ else
+ {
+ ACE_ALLOCATOR_RETURN (data,
+ shmem_response->malloc (ACE_OS::strlen (response_string) + 1),
+ 1);
+ ACE_OS::strcpy ((char *) data,
+ response_string);
+
+ if (shmem_response->bind ("foo",
+ data) == -1)
+ ACE_ERROR ((LM_ERROR,
+ "%p\n",
+ "bind"));
+ else
+ ACE_DEBUG ((LM_DEBUG,
+ "Run again to see results and release resources.\n"));
+ }
+
+ return 0;
+}
+
diff --git a/ACE/examples/Shared_Malloc/test_persistence.cpp b/ACE/examples/Shared_Malloc/test_persistence.cpp
new file mode 100644
index 00000000000..8c3df750853
--- /dev/null
+++ b/ACE/examples/Shared_Malloc/test_persistence.cpp
@@ -0,0 +1,350 @@
+// $Id$
+
+// Test the persistence capabilities of <ACE_Malloc> when configured
+// for mmap-based shared memory management.
+
+// This examples uses scanf to read user inputs from stdin into fixed
+// sized buffers. This may cause buffers to overrun.
+
+#include "ace/OS_NS_string.h"
+#include "ace/Malloc_T.h"
+#include "ace/MMAP_Memory_Pool.h"
+
+// FUZZ: disable check_for_streams_include
+#include "ace/streams.h"
+
+#include "ace/Null_Mutex.h"
+
+ACE_RCSID (Shared_Malloc,
+ test_persistence,
+ "$Id$")
+
+typedef ACE_Malloc <ACE_MMAP_MEMORY_POOL, ACE_Null_Mutex> TEST_MALLOC;
+typedef ACE_Malloc_LIFO_Iterator <ACE_MMAP_MEMORY_POOL, ACE_Null_Mutex> MALLOC_LIFO_ITERATOR;
+typedef ACE_Malloc_FIFO_Iterator <ACE_MMAP_MEMORY_POOL, ACE_Null_Mutex> MALLOC_FIFO_ITERATOR;
+
+// Shared memory manager.
+static TEST_MALLOC *shmem_allocator = 0;
+
+// Backing store name.
+static ACE_TCHAR backing_store[MAXPATHLEN + 1] = ACE_TEXT ("");
+
+class Employee
+{
+public:
+ Employee (void): name_ (0), id_ (0) {}
+
+ Employee (const char *name, u_long id) : id_ (id)
+ {
+ size_t len = ACE_OS::strlen (name) + 1;
+ this->name_ = reinterpret_cast<char *> (shmem_allocator->malloc (len));
+ ACE_OS::strcpy (this->name_, name);
+ }
+
+ ~Employee (void) { shmem_allocator->free (this->name_); }
+
+ const char *name (void) const { return this->name_; }
+
+ void name (const char *name)
+ {
+ if (this->name_)
+ shmem_allocator->free (this->name_);
+
+ size_t len = ACE_OS::strlen (name) + 1;
+ this->name_ = reinterpret_cast<char *> (shmem_allocator->malloc (len));
+ ACE_OS::strcpy (this->name_, name);
+ }
+
+ u_long id (void) const { return id_; }
+
+ void id (u_long id) { id_ = id; }
+
+ void *operator new (size_t)
+ {
+ return shmem_allocator->malloc (sizeof (Employee));
+ }
+
+#if defined (ACE_HAS_NEW_NOTHROW)
+ void *operator new (size_t, const ACE_nothrow_t&)
+ {
+ return shmem_allocator->malloc (sizeof (Employee));
+ }
+#if !defined (ACE_LACKS_PLACEMENT_OPERATOR_DELETE)
+ void operator delete (void *p, const ACE_nothrow_t&) throw ()
+ {
+ shmem_allocator->free (p);
+ }
+#endif /* ACE_LACKS_PLACEMENT_OPERATOR_DELETE */
+#endif
+
+ void operator delete (void *pointer)
+ {
+ shmem_allocator->free (pointer);
+ }
+
+private:
+ char *name_;
+ // Employee name.
+
+ u_long id_;
+ // Employee ID.
+};
+
+class GUI_Handler
+{
+public:
+ GUI_Handler (void) { menu (); }
+
+ ~GUI_Handler (void)
+ {
+ TEST_MALLOC::MEMORY_POOL &pool =
+ shmem_allocator->memory_pool ();
+ pool.sync ();
+ }
+
+ int service(void)
+ {
+ char option[BUFSIZ];
+ char buf1[BUFSIZ];
+ char buf2[BUFSIZ];
+
+ if (::scanf ("%s", option) <= 0)
+ {
+ ACE_ERROR ((LM_ERROR,
+ "try again\n"));
+ return 0;
+ }
+
+ int result = 0;
+ switch (option[0])
+ {
+ case 'I' :
+ case 'i' :
+ if (::scanf ("%s %s", buf1, buf2) <= 0)
+ break;
+ result = insert_employee (buf1,
+ ACE_OS::atoi (buf2));
+ break;
+ case 'F' :
+ case 'f' :
+ if (::scanf ("%s", buf1) <= 0)
+ break;
+ result = find_employee (buf1);
+ break;
+ case 'D' :
+ case 'd' :
+ if (::scanf ("%s", buf1) <= 0)
+ break;
+ result = delete_employee (buf1);
+ break;
+ case 'L' :
+ case 'l' :
+ result = list_employees ();
+ break;
+ case 'Q' :
+ case 'q' :
+ return -1;
+ ACE_NOTREACHED(break);
+ default :
+ cout << "unrecognized command" << endl;
+ }
+ if (result == 0)
+ cout << "Last operation was successful!!" << endl;
+ else
+ cout << "Last operation failed!! " << endl;
+
+ menu ();
+
+ return 0;
+ }
+
+ void menu(void)
+ {
+ cout << endl;
+ cout << "\t************************** " << endl;
+ cout << "\tThe employee database menu " << endl;
+ cout << endl;
+ cout << "\t<I> Insert <name> <id> " << endl;
+ cout << "\t<D> Delete <name> " << endl;
+ cout << "\t<F> Find <name> " << endl;
+ cout << endl;
+ cout << "\t<L> List all employees " << endl;
+ cout << endl;
+ cout << "\t<Q> Quit " << endl;
+ cout << "\t************************** " << endl;
+ }
+
+private:
+ int insert_employee (const char *name,
+ u_long id);
+ int find_employee (const char *name);
+ int list_employees (void);
+ int delete_employee (const char *name);
+};
+
+int
+GUI_Handler::insert_employee (const char *name,
+ u_long id)
+{
+ if (find_employee (name) == 0)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Employee already exists\n"),
+ -1);
+
+ Employee *new_employee = 0;
+
+ ACE_NEW_RETURN (new_employee,
+ Employee (name, id),
+ -1);
+
+ if (shmem_allocator->bind (name,
+ new_employee) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "bind failed\n"),
+ -1);
+ return 0;
+}
+
+int
+GUI_Handler::find_employee (const char *name)
+{
+ void *temp = 0;
+
+ if (shmem_allocator->find (name,
+ temp) == 0)
+ {
+ Employee *employee = reinterpret_cast<Employee *> (temp);
+
+ ACE_DEBUG ((LM_DEBUG,
+ "The following employee was found.......\n\n"));
+ ACE_DEBUG ((LM_DEBUG,
+ "Employee name: %s\nEmployee id: %d\n",
+ employee->name (),
+ employee->id ()));
+ return 0;
+ }
+
+ return -1;
+}
+
+int
+GUI_Handler::list_employees (void)
+{
+ ACE_DEBUG ((LM_DEBUG,
+ "The following employees were found.......\n\n"));
+
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ "LIFO order:\n"));
+ MALLOC_LIFO_ITERATOR iterator (*shmem_allocator);
+
+ for (void *temp = 0;
+ iterator.next (temp) != 0;
+ iterator.advance ())
+ {
+ Employee *employee = reinterpret_cast<Employee *> (temp);
+ ACE_DEBUG ((LM_DEBUG,
+ "Employee name: %s\nEmployee id: %d\n",
+ employee->name (),
+ employee->id ()));
+ }
+ }
+
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ "FIFO order:\n"));
+ MALLOC_FIFO_ITERATOR iterator (*shmem_allocator);
+
+ for (void *temp = 0;
+ iterator.next (temp) != 0;
+ iterator.advance ())
+ {
+ Employee *employee = reinterpret_cast<Employee *> (temp);
+ ACE_DEBUG ((LM_DEBUG,
+ "Employee name: %s\nEmployee id: %d\n",
+ employee->name (),
+ employee->id ()));
+ }
+ }
+ return 0;
+}
+
+int
+GUI_Handler::delete_employee (const char *name)
+{
+ void *temp = 0;
+
+ if (shmem_allocator->unbind (name,
+ temp) == 0)
+ {
+ Employee *employee = reinterpret_cast<Employee *> (temp);
+
+ ACE_DEBUG ((LM_DEBUG,
+ "The following employee was found and deleted.......\n\n"));
+
+ ACE_DEBUG ((LM_DEBUG,
+ "Employee name: %s\nEmployee id: %d\n",
+ employee->name (),
+ employee->id ()));
+
+ delete employee;
+ return 0;
+ }
+
+ ACE_DEBUG ((LM_DEBUG,
+ "There is no employee with name %s",
+ name));
+ return -1;
+}
+
+void
+parse_args (int argc, ACE_TCHAR *argv[])
+{
+ if (argc > 1)
+ ACE_OS::strcpy (backing_store, argv[1]);
+}
+
+int
+ACE_TMAIN (int argc, ACE_TCHAR *argv[])
+{
+ parse_args (argc, argv);
+
+ if (ACE_OS::strcmp (backing_store, ACE_TEXT ("")) == 0)
+ {
+#if defined (ACE_DEFAULT_BACKING_STORE)
+ // Create a temporary file.
+ ACE_OS::strcpy (backing_store,
+ ACE_DEFAULT_BACKING_STORE);
+#else /* ACE_DEFAULT_BACKING_STORE */
+ if (ACE::get_temp_dir (backing_store,
+ MAXPATHLEN - 17) == -1) // -17 for ace-malloc-XXXXXX
+ {
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("Temporary path too long, ")
+ ACE_TEXT ("defaulting to current directory\n")));
+ backing_store[0] = 0;
+ }
+
+ // Add the filename to the end
+ ACE_OS::strcat (backing_store, ACE_TEXT ("ace-malloc-XXXXXX"));
+
+#endif /* ACE_DEFAULT_BACKING_STORE */
+ }
+
+ ACE_NEW_RETURN (shmem_allocator,
+ TEST_MALLOC (backing_store),
+ -1);
+
+ GUI_Handler handler;
+
+ for (;;)
+ if (handler.service () == -1)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("closing down ....\n")));
+ break;
+ }
+
+ return 0;
+}
+
diff --git a/ACE/examples/Shared_Malloc/test_position_independent_malloc.cpp b/ACE/examples/Shared_Malloc/test_position_independent_malloc.cpp
new file mode 100644
index 00000000000..b4c66e54957
--- /dev/null
+++ b/ACE/examples/Shared_Malloc/test_position_independent_malloc.cpp
@@ -0,0 +1,190 @@
+// $Id$
+
+// Test the capability of the "position-independent" <ACE_Malloc> to
+// handle a single malloc that can be rooted at different base
+// addresses each time it's used. The actual backing store used by
+// <ACE_Malloc> is located in a memory-mapped file.
+
+#include "test_position_independent_malloc.h"
+#include "ace/PI_Malloc.h"
+#include "ace/Based_Pointer_T.h"
+#include "ace/Get_Opt.h"
+#include "ace/Auto_Ptr.h"
+#include "ace/Process_Mutex.h"
+#include "ace/Malloc_T.h"
+#include "ace/MMAP_Memory_Pool.h"
+
+ACE_RCSID(Shared_Malloc, test_multiple_mallocs, "$Id$")
+
+#if (ACE_HAS_POSITION_INDEPENDENT_POINTERS == 1)
+typedef ACE_PI_Control_Block CONTROL_BLOCK;
+#else
+typedef ACE_Control_Block CONTROL_BLOCK;
+#endif /* ACE_HAS_POSITION_INDEPENDENT_POINTERS == 1 */
+
+typedef ACE_Malloc_T <ACE_MMAP_MEMORY_POOL, ACE_Process_Mutex, CONTROL_BLOCK> TEST_MALLOC;
+
+// Default address for memory-mapped files.
+static void *base_addr = ACE_DEFAULT_BASE_ADDR;
+
+static void
+print (Test_Data *data)
+{
+ for (Test_Data *t = data; t != 0; t = t->next_)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ "<<<<\ni1_ = %d, i2_ = %d, i3_ = %d\n",
+ t->i1_,
+ t->i2_,
+ t->i3_));
+ ACE_DEBUG ((LM_DEBUG,
+ "*t->bpl_ = %d, t->long_test_->array_[0] = %d\n>>>>\n",
+ *t->long_test_->bpl_,
+ t->long_test_->array_[0]));
+ }
+}
+
+static void *
+initialize (TEST_MALLOC *allocator)
+{
+ void *ptr;
+ ACE_ALLOCATOR_RETURN (ptr,
+ allocator->malloc (sizeof (Test_Data)),
+ 0);
+ Test_Data *data1 = new (ptr) Test_Data;
+
+ data1->i1_ = 111;
+ data1->i2_ = 222;
+ data1->i3_ = 333;
+
+ void *gap = 0;
+ ACE_ALLOCATOR_RETURN (gap,
+ allocator->malloc (sizeof (256)),
+ 0);
+
+ allocator->free (gap);
+
+ ACE_ALLOCATOR_RETURN (ptr,
+ allocator->malloc (sizeof (Test_Data)),
+ 0);
+ Test_Data *data2 = new (ptr) Test_Data;
+
+ data1->next_ = 0;
+ data1->i1_ = 111;
+ data1->i2_ = 222;
+ data1->i3_ = 333;
+ data2->next_ = data1;
+ data2->i1_ = -111;
+ data2->i2_ = -222;
+ data2->i3_ = -333;
+
+ // Test in shared memory using long (array/pointer)
+ ACE_ALLOCATOR_RETURN (ptr,
+ allocator->malloc (sizeof (Long_Test)),
+ 0);
+ Long_Test *lt = new (ptr) Long_Test;
+
+ lt->array_[0] = 1000;
+ lt->array_[1] = 1001;
+ lt->array_[2] = 1002;
+ lt->array_[3] = 1003;
+ lt->array_[4] = 1004;
+ lt->bpl_ = lt->array_;
+
+ data1->long_test_= lt;
+
+ ACE_ASSERT (*lt->bpl_ == 1000);
+ ACE_ASSERT (lt->bpl_[3] == 1003);
+
+ ACE_ALLOCATOR_RETURN (ptr,
+ allocator->malloc (sizeof (Long_Test)),
+ 0);
+ lt = new (ptr) Long_Test;
+
+ lt->array_[0] = 2000;
+ lt->array_[1] = 2001;
+ lt->array_[2] = 2002;
+ lt->array_[3] = 2003;
+ lt->array_[4] = 2004;
+ lt->bpl_ = lt->array_;
+
+ data2->long_test_= lt;
+
+ ACE_ASSERT (*lt->bpl_ == 2000);
+ ACE_ASSERT (lt->bpl_[4] == 2004);
+
+ return data2;
+}
+
+static void
+parse_args (int argc, ACE_TCHAR *argv[])
+{
+ ACE_Get_Opt get_opt (argc, argv, ACE_TEXT("a:T"));
+
+ for (int c;
+ (c = get_opt ()) != -1;
+ )
+ {
+ switch (c)
+ {
+ case 'a':
+ // Override the default base address.
+ base_addr = reinterpret_cast<void *> (ACE_OS::atoi (get_opt.opt_arg ()));
+ break;
+ case 'T':
+#if defined (ACE_HAS_TRACE)
+ ACE_Trace::start_tracing ();
+#endif /* ACE_HAS_TRACE */
+ break;
+ }
+ }
+}
+
+int
+ACE_TMAIN (int argc, ACE_TCHAR *argv[])
+{
+ parse_args (argc, argv);
+
+ ACE_MMAP_Memory_Pool_Options options (base_addr);
+
+ // Create an allocator.
+ TEST_MALLOC *ptr = 0;
+ ACE_NEW_RETURN (ptr,
+ TEST_MALLOC (ACE_TEXT("test_file"),
+ ACE_TEXT("test_lock"),
+ &options),
+ 1);
+ auto_ptr <TEST_MALLOC> allocator (ptr);
+ void *data = 0;
+
+ // This is the first time in, so we allocate the memory and bind it
+ // to the name "foo".
+ if (allocator->find ("foo",
+ data) == -1)
+ {
+ data = initialize (allocator.get ());
+
+ if (allocator->bind ("foo",
+ data) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%p\n",
+ "bind"),
+ 1);
+
+ ACE_DEBUG ((LM_DEBUG,
+ "Run again to see results and release resources.\n"));
+ }
+ // If we find "foo" then we're running the "second" time, so we must
+ // release the resources.
+ else
+ {
+ print ((Test_Data *) data);
+ allocator->free (data);
+ allocator->remove ();
+ ACE_DEBUG ((LM_DEBUG,
+ "all resources released\n"));
+ }
+
+ return 0;
+}
+
diff --git a/ACE/examples/Shared_Malloc/test_position_independent_malloc.h b/ACE/examples/Shared_Malloc/test_position_independent_malloc.h
new file mode 100644
index 00000000000..2785a386045
--- /dev/null
+++ b/ACE/examples/Shared_Malloc/test_position_independent_malloc.h
@@ -0,0 +1,28 @@
+// $Id$
+//
+// Define struct used in test_position_independent_malloc.cpp - needs
+// to be in a separate file for template generation on AIX IBM C++.
+
+#ifndef __TEST_POSITION_INDEPENDENT_MALLOC_H
+#define __TEST_POSITION_INDEPENDENT_MALLOC_H
+
+#include "ace/Based_Pointer_T.h"
+
+// Some test data.
+struct Long_Test
+{
+ ACE_Based_Pointer_Basic<long> bpl_;
+ long array_[10];
+};
+
+// Some more test data.
+struct Test_Data
+{
+ int i1_;
+ int i2_;
+ int i3_;
+ ACE_Based_Pointer<Test_Data> next_;
+ ACE_Based_Pointer<Long_Test> long_test_;
+};
+
+#endif /* __TEST_POSITION_INDEPENDENT_MALLOC */
diff --git a/ACE/examples/Shared_Memory/.cvsignore b/ACE/examples/Shared_Memory/.cvsignore
new file mode 100644
index 00000000000..7f6e8a792c5
--- /dev/null
+++ b/ACE/examples/Shared_Memory/.cvsignore
@@ -0,0 +1,2 @@
+testmm
+testsv
diff --git a/ACE/examples/Shared_Memory/Makefile.am b/ACE/examples/Shared_Memory/Makefile.am
new file mode 100644
index 00000000000..864c7a5b071
--- /dev/null
+++ b/ACE/examples/Shared_Memory/Makefile.am
@@ -0,0 +1,56 @@
+## Process this file with automake to create Makefile.in
+##
+## $Id$
+##
+## This file was generated by MPC. Any changes made directly to
+## this file will be lost the next time it is generated.
+##
+## MPC Command:
+## /acebuilds/ACE_wrappers-repository/bin/mwc.pl -include /acebuilds/MPC/config -include /acebuilds/MPC/templates -feature_file /acebuilds/ACE_wrappers-repository/local.features -noreldefs -type automake -exclude build,Kokyu
+
+ACE_BUILDDIR = $(top_builddir)
+ACE_ROOT = $(top_srcdir)
+
+noinst_PROGRAMS =
+
+## Makefile.Shared_Memory_MM.am
+
+if !BUILD_ACE_FOR_TAO
+noinst_PROGRAMS += testmm
+
+testmm_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+testmm_SOURCES = \
+ test_MM.cpp
+
+testmm_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+endif !BUILD_ACE_FOR_TAO
+
+## Makefile.Shared_Memory_SV.am
+
+if !BUILD_ACE_FOR_TAO
+noinst_PROGRAMS += testsv
+
+testsv_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+testsv_SOURCES = \
+ test_SV.cpp
+
+testsv_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+endif !BUILD_ACE_FOR_TAO
+
+## Clean up template repositories, etc.
+clean-local:
+ -rm -f *~ *.bak *.rpo *.sym lib*.*_pure_* core core.*
+ -rm -f gcctemp.c gcctemp so_locations *.ics
+ -rm -rf cxx_repository ptrepository ti_files
+ -rm -rf templateregistry ir.out
+ -rm -rf ptrepository SunWS_cache Templates.DB
diff --git a/ACE/examples/Shared_Memory/Shared_Memory.mpc b/ACE/examples/Shared_Memory/Shared_Memory.mpc
new file mode 100644
index 00000000000..f0ee256597b
--- /dev/null
+++ b/ACE/examples/Shared_Memory/Shared_Memory.mpc
@@ -0,0 +1,17 @@
+// -*- MPC -*-
+// $Id$
+
+project(*MM) : aceexe {
+ avoids += ace_for_tao
+ exename = testmm
+ Source_Files {
+ test_MM.cpp
+ }
+}
+project(*SV) : aceexe {
+ avoids += ace_for_tao
+ exename = testsv
+ Source_Files {
+ test_SV.cpp
+ }
+}
diff --git a/ACE/examples/Shared_Memory/test_MM.cpp b/ACE/examples/Shared_Memory/test_MM.cpp
new file mode 100644
index 00000000000..2d98224f910
--- /dev/null
+++ b/ACE/examples/Shared_Memory/test_MM.cpp
@@ -0,0 +1,74 @@
+// $Id$
+
+#include "ace/Shared_Memory_MM.h"
+#include "ace/Log_Msg.h"
+#include "ace/OS_NS_errno.h"
+#include "ace/OS_NS_unistd.h"
+#include "ace/OS_NS_stdlib.h"
+
+ACE_RCSID(Shared_Memory, test_MM, "$Id$")
+
+#define SHMSZ 27
+ACE_TCHAR shm_key[] = ACE_TEXT ("/tmp/fooXXXXXX");
+
+static void
+client (void)
+{
+ ACE_Shared_Memory *shm_client = new ACE_Shared_Memory_MM (shm_key);
+ char *shm = (char *) shm_client->malloc ();
+
+ for (char *s = shm; *s != '\0'; s++)
+ putchar (*s);
+
+ putchar ('\n');
+ *shm = '*';
+}
+
+static void
+server (void)
+{
+ ACE_Shared_Memory *shm_server = new ACE_Shared_Memory_MM (shm_key, SHMSZ);
+ char *shm = (char *) shm_server->malloc ();
+ char *s = shm;
+
+ for (char c = 'a'; c <= 'z'; c++)
+ *s++ = c;
+
+ *s = '\0';
+
+ // Perform a busy wait (ugh)
+ while (*shm != '*')
+ ACE_OS::sleep (1);
+
+ if (shm_server->remove () < 0)
+ ACE_ERROR ((LM_ERROR, ACE_TEXT ("%p\n"), ACE_TEXT ("remove")));
+ ACE_OS::unlink (shm_key);
+}
+
+int
+ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ if (
+#if defined (ACE_LACKS_MKSTEMP)
+ ACE_OS::mktemp (shm_key) == 0
+#else
+ ACE_OS::mkstemp (shm_key) == 0
+#endif
+ || (ACE_OS::unlink (shm_key) == -1 && errno == EPERM))
+ ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("%p\n"), shm_key), 1);
+
+ switch (ACE_OS::fork ())
+ {
+ case -1:
+ ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("%p\n"), ACE_TEXT ("fork")), 1);
+ case 0:
+ // Make sure the server starts up first.
+ ACE_OS::sleep (1);
+ client ();
+ break;
+ default:
+ server ();
+ break;
+ }
+ return 0;
+}
diff --git a/ACE/examples/Shared_Memory/test_SV.cpp b/ACE/examples/Shared_Memory/test_SV.cpp
new file mode 100644
index 00000000000..26ab56a7115
--- /dev/null
+++ b/ACE/examples/Shared_Memory/test_SV.cpp
@@ -0,0 +1,64 @@
+// $Id$
+
+#include "ace/Shared_Memory_SV.h"
+#include "ace/Log_Msg.h"
+#include "ace/OS_NS_unistd.h"
+
+ACE_RCSID(Shared_Memory, test_SV, "$Id$")
+
+#define SHMSZ 27
+#define SHM_KEY (key_t) 5678
+
+static void
+client (void)
+{
+ ACE_Shared_Memory_SV shm_client (SHM_KEY, SHMSZ);
+ char *shm = (char *) shm_client.malloc ();
+
+ for (char *s = shm; *s != '\0'; s++)
+ putchar (*s);
+
+ putchar ('\n');
+ *shm = '*';
+}
+
+static void
+server (void)
+{
+ ACE_Shared_Memory_SV shm_server (SHM_KEY, SHMSZ,
+ ACE_Shared_Memory_SV::ACE_CREATE);
+ char *shm = (char *) shm_server.malloc ();
+ char *s = shm;
+
+ for (char c = 'a'; c <= 'z'; c++)
+ *s++ = c;
+
+ *s = '\0';
+
+ while (*shm != '*')
+ ACE_OS::sleep (1);
+
+ if (shm_server.remove () < 0)
+ ACE_ERROR ((LM_ERROR, "%p\n", "remove"));
+}
+
+int
+ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ switch (ACE_OS::fork ())
+ {
+ case -1:
+ ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "fork"), 1);
+ case 0:
+ // Make sure the server starts up first.
+ ACE_OS::sleep (1);
+ client ();
+ break;
+ default:
+ server ();
+ break;
+ }
+
+ return 0;
+}
+
diff --git a/ACE/examples/Smart_Pointers/.cvsignore b/ACE/examples/Smart_Pointers/.cvsignore
new file mode 100644
index 00000000000..f309b7d5f8b
--- /dev/null
+++ b/ACE/examples/Smart_Pointers/.cvsignore
@@ -0,0 +1,2 @@
+Widget
+gadget
diff --git a/ACE/examples/Smart_Pointers/Gadget.cpp b/ACE/examples/Smart_Pointers/Gadget.cpp
new file mode 100644
index 00000000000..180fe0107cc
--- /dev/null
+++ b/ACE/examples/Smart_Pointers/Gadget.cpp
@@ -0,0 +1,16 @@
+/* -*- C++ -*- */
+//=============================================================================
+/**
+ * @file Gadget.cpp
+ *
+ * $Id$
+ *
+ * @author Christopher Kohlhoff <chris@kohlhoff.com>
+ */
+//=============================================================================
+
+#include "Gadget.h"
+
+Gadget::~Gadget (void)
+{
+}
diff --git a/ACE/examples/Smart_Pointers/Gadget.h b/ACE/examples/Smart_Pointers/Gadget.h
new file mode 100644
index 00000000000..65b1fb0a34e
--- /dev/null
+++ b/ACE/examples/Smart_Pointers/Gadget.h
@@ -0,0 +1,51 @@
+/* -*- C++ -*- */
+//=============================================================================
+/**
+ * @file Gadget.h
+ *
+ * $Id$
+ *
+ * @author Christopher Kohlhoff <chris@kohlhoff.com>
+ */
+//=============================================================================
+
+#ifndef GADGET_H
+#define GADGET_H
+
+#include "ace/Bound_Ptr.h"
+#include "Gadget_Part.h"
+
+/**
+ * @class Gadget
+ *
+ * @brief An interface for some high-level application object.
+ */
+class Gadget
+{
+public:
+ /// Destructor.
+ virtual ~Gadget (void);
+
+ /// Add a new part to the gadget. The gadget automatically takes shared
+ /// responsibility for the ownership of the part object since we are passing
+ /// a Gadget_Part_var.
+ virtual void add_part (Gadget_Part_var part) = 0;
+
+ /// Remove a random part from the gadget. Responsibility for ownership of the
+ /// part is automatically returned to the caller since we are returning a
+ /// Gadget_Part_var.
+ virtual Gadget_Part_var remove_part (void) = 0;
+
+ /// Ask the gadget to print information about the parts that it contains.
+ virtual void list_parts (void) = 0;
+};
+
+// The Gadget_var smart pointer has shared (reference counted) ownership
+// semantics.
+typedef ACE_Strong_Bound_Ptr<Gadget, ACE_SYNCH_MUTEX> Gadget_var;
+
+// The Gadget_ptr smart pointer has no ownership semantics, but supports
+// conversion back into a Gadget_var.
+typedef ACE_Weak_Bound_Ptr<Gadget, ACE_SYNCH_MUTEX> Gadget_ptr;
+
+#endif /* GADGET_H */
diff --git a/ACE/examples/Smart_Pointers/Gadget_Factory.cpp b/ACE/examples/Smart_Pointers/Gadget_Factory.cpp
new file mode 100644
index 00000000000..054237169f2
--- /dev/null
+++ b/ACE/examples/Smart_Pointers/Gadget_Factory.cpp
@@ -0,0 +1,18 @@
+/* -*- C++ -*- */
+//=============================================================================
+/**
+ * @file Gadget_Factory.cpp
+ *
+ * $Id$
+ *
+ * @author Christopher Kohlhoff <chris@kohlhoff.com>
+ */
+//=============================================================================
+
+#include "Gadget_Factory.h"
+#include "Gadget_Impl.h"
+
+Gadget_var Gadget_Factory::create_gadget (void)
+{
+ return Gadget_var (new Gadget_Impl);
+}
diff --git a/ACE/examples/Smart_Pointers/Gadget_Factory.h b/ACE/examples/Smart_Pointers/Gadget_Factory.h
new file mode 100644
index 00000000000..dd3c17e7975
--- /dev/null
+++ b/ACE/examples/Smart_Pointers/Gadget_Factory.h
@@ -0,0 +1,32 @@
+/* -*- C++ -*- */
+//=============================================================================
+/**
+ * @file Gadget_Factory.h
+ *
+ * $Id$
+ *
+ * @author Christopher Kohlhoff <chris@kohlhoff.com>
+ */
+//=============================================================================
+
+#ifndef GADGET_FACTORY_H
+#define GADGET_FACTORY_H
+
+#include "Gadget.h"
+
+/**
+ * @class Gadget_Factory
+ *
+ * @brief Used to create Gadget instances.
+ */
+class Gadget_Factory
+{
+public:
+ /// Create an instance of a gadget. Ownership of the object is automatically
+ /// transferred to the caller since we return a Gadget_var. This also means
+ /// that the object will be deleted automatically if the caller "forgets" to
+ /// collect the return value.
+ static Gadget_var create_gadget (void);
+};
+
+#endif /* GADGET_FACTORY_H */
diff --git a/ACE/examples/Smart_Pointers/Gadget_Impl.cpp b/ACE/examples/Smart_Pointers/Gadget_Impl.cpp
new file mode 100644
index 00000000000..03dd94f8838
--- /dev/null
+++ b/ACE/examples/Smart_Pointers/Gadget_Impl.cpp
@@ -0,0 +1,47 @@
+/* -*- C++ -*- */
+//=============================================================================
+/**
+ * @file Gadget_Impl.cpp
+ *
+ * $Id$
+ *
+ * @author Christopher Kohlhoff <chris@kohlhoff.com>
+ */
+//=============================================================================
+
+#include "Gadget_Impl.h"
+#include "ace/Log_Msg.h"
+
+Gadget_Impl::Gadget_Impl (void)
+{
+ ACE_DEBUG ((LM_DEBUG, "Gadget_Impl constructor\n"));
+}
+
+Gadget_Impl::~Gadget_Impl (void)
+{
+ ACE_DEBUG ((LM_DEBUG, "Gadget_Impl destructor\n"));
+}
+
+void Gadget_Impl::add_part (Gadget_Part_var part)
+{
+ parts_.enqueue_tail (part);
+}
+
+Gadget_Part_var Gadget_Impl::remove_part (void)
+{
+ Gadget_Part_var removed_part;
+ if (parts_.dequeue_head (removed_part) == -1)
+ return Gadget_Part_var();
+ return removed_part;
+}
+
+void Gadget_Impl::list_parts (void)
+{
+ ACE_Unbounded_Queue_Iterator<Gadget_Part_var> iter (parts_);
+ Gadget_Part_var *current_part;
+ while (iter.next (current_part))
+ {
+ (*current_part)->print_info ();
+ iter.advance ();
+ }
+}
diff --git a/ACE/examples/Smart_Pointers/Gadget_Impl.h b/ACE/examples/Smart_Pointers/Gadget_Impl.h
new file mode 100644
index 00000000000..ed4faf27ca4
--- /dev/null
+++ b/ACE/examples/Smart_Pointers/Gadget_Impl.h
@@ -0,0 +1,51 @@
+/* -*- C++ -*- */
+//=============================================================================
+/**
+ * @file Gadget_Impl.h
+ *
+ * $Id$
+ *
+ * @author Christopher Kohlhoff <chris@kohlhoff.com>
+ */
+//=============================================================================
+
+#ifndef GADGET_IMPL_H
+#define GADGET_IMPL_H
+
+#include "ace/Unbounded_Queue.h"
+#include "Gadget.h"
+#include "Gadget_Part.h"
+
+/**
+ * @class Gadget_Impl
+ *
+ * @brief An implementation of the Gadget interface.
+ */
+class Gadget_Impl : public Gadget
+{
+public:
+ /// Constructor.
+ Gadget_Impl (void);
+
+ /// Destructor.
+ virtual ~Gadget_Impl (void);
+
+ /// Add a new part to the gadget. The gadget takes ownership of the part
+ /// object.
+ virtual void add_part (Gadget_Part_var part);
+
+ /// Remove a random part from the gadget. Ownership of the part is returned
+ /// to the caller.
+ virtual Gadget_Part_var remove_part (void);
+
+ /// Ask the gadget to print information about the parts that it contains.
+ virtual void list_parts (void);
+
+private:
+ /// The parts which make up this gadget. The set actually contains instances
+ /// of Gadget_Part_var to automatically manage the lifetimes of the
+ /// constituent parts.
+ ACE_Unbounded_Queue<Gadget_Part_var> parts_;
+};
+
+#endif /* GADGET_IMPL_H */
diff --git a/ACE/examples/Smart_Pointers/Gadget_Part.cpp b/ACE/examples/Smart_Pointers/Gadget_Part.cpp
new file mode 100644
index 00000000000..9f08f2a61e7
--- /dev/null
+++ b/ACE/examples/Smart_Pointers/Gadget_Part.cpp
@@ -0,0 +1,16 @@
+/* -*- C++ -*- */
+//=============================================================================
+/**
+ * @file Gadget_Part.cpp
+ *
+ * $Id$
+ *
+ * @author Christopher Kohlhoff <chris@kohlhoff.com>
+ */
+//=============================================================================
+
+#include "Gadget_Part.h"
+
+Gadget_Part::~Gadget_Part (void)
+{
+}
diff --git a/ACE/examples/Smart_Pointers/Gadget_Part.h b/ACE/examples/Smart_Pointers/Gadget_Part.h
new file mode 100644
index 00000000000..cef4277168a
--- /dev/null
+++ b/ACE/examples/Smart_Pointers/Gadget_Part.h
@@ -0,0 +1,45 @@
+/* -*- C++ -*- */
+//=============================================================================
+/**
+ * @file Gadget_Part.h
+ *
+ * $Id$
+ *
+ * @author Christopher Kohlhoff <chris@kohlhoff.com>
+ */
+//=============================================================================
+
+#ifndef GADGET_PART_H
+#define GADGET_PART_H
+
+#include "ace/Bound_Ptr.h"
+#include "ace/Synch_Traits.h"
+#include "ace/Thread_Mutex.h"
+
+/**
+ * @class Gadget_Part
+ *
+ * @brief An interface for some high-level application object.
+ */
+class Gadget_Part
+{
+public:
+ /// Destructor.
+ virtual ~Gadget_Part (void);
+
+ /// Ask the part to print information about itself.
+ virtual void print_info (void) = 0;
+
+ /// Ask the part to remove itself from the gadget that contains it.
+ virtual void remove_from_owner (void) = 0;
+};
+
+// The Gadget_Part_var smart pointer has shared (reference counted) ownership
+// semantics.
+typedef ACE_Strong_Bound_Ptr<Gadget_Part, ACE_SYNCH_MUTEX> Gadget_Part_var;
+
+// The Gadget_Part_ptr smart pointer has no ownership semantics, but supports
+// conversion back into a Gadget_var.
+typedef ACE_Weak_Bound_Ptr<Gadget_Part, ACE_SYNCH_MUTEX> Gadget_Part_ptr;
+
+#endif /* GADGET_PART_H */
diff --git a/ACE/examples/Smart_Pointers/Gadget_Part_Factory.cpp b/ACE/examples/Smart_Pointers/Gadget_Part_Factory.cpp
new file mode 100644
index 00000000000..caf546fffce
--- /dev/null
+++ b/ACE/examples/Smart_Pointers/Gadget_Part_Factory.cpp
@@ -0,0 +1,20 @@
+/* -*- C++ -*- */
+//=============================================================================
+/**
+ * @file Gadget_Part_Factory.cpp
+ *
+ * $Id$
+ *
+ * @author Christopher Kohlhoff <chris@kohlhoff.com>
+ */
+//=============================================================================
+
+#include "Gadget_Part_Factory.h"
+#include "Gadget_Part_Impl.h"
+
+Gadget_Part_var Gadget_Part_Factory::create_gadget_part (Gadget_ptr owner,
+ const char* name,
+ int size)
+{
+ return Gadget_Part_var (new Gadget_Part_Impl (owner, name, size));
+}
diff --git a/ACE/examples/Smart_Pointers/Gadget_Part_Factory.h b/ACE/examples/Smart_Pointers/Gadget_Part_Factory.h
new file mode 100644
index 00000000000..a7bc5cb38bd
--- /dev/null
+++ b/ACE/examples/Smart_Pointers/Gadget_Part_Factory.h
@@ -0,0 +1,35 @@
+/* -*- C++ -*- */
+//=============================================================================
+/**
+ * @file Gadget_Part_Factory.h
+ *
+ * $Id$
+ *
+ * @author Christopher Kohlhoff <chris@kohlhoff.com>
+ */
+//=============================================================================
+
+#ifndef GADGET_PART_FACTORY_H
+#define GADGET_PART_FACTORY_H
+
+#include "Gadget_Part.h"
+#include "Gadget.h"
+
+/**
+ * @class Gadget_Part_Factory
+ *
+ * @brief Used to create Gadget_Part instances.
+ */
+class Gadget_Part_Factory
+{
+public:
+ /// Create an instance of a gadget. Ownership of the object is automatically
+ /// transferred to the caller since we return a Gadget_Part_var. This also
+ /// means that the object will be deleted automatically if the caller
+ /// "forgets" to collect the return value.
+ static Gadget_Part_var create_gadget_part (Gadget_ptr owner,
+ const char *name,
+ int size);
+};
+
+#endif /* GADGET_PART_FACTORY_H */
diff --git a/ACE/examples/Smart_Pointers/Gadget_Part_Impl.cpp b/ACE/examples/Smart_Pointers/Gadget_Part_Impl.cpp
new file mode 100644
index 00000000000..aeda00711bb
--- /dev/null
+++ b/ACE/examples/Smart_Pointers/Gadget_Part_Impl.cpp
@@ -0,0 +1,68 @@
+/* -*- C++ -*- */
+//=============================================================================
+/**
+ * @file Gadget_Part_Impl.cpp
+ *
+ * $Id$
+ *
+ * @author Christopher Kohlhoff <chris@kohlhoff.com>
+ */
+//=============================================================================
+
+#include "Gadget_Part_Impl.h"
+#include "ace/ACE.h"
+#include "ace/Log_Msg.h"
+#include "ace/Unbounded_Queue.h"
+
+Gadget_Part_Impl::Gadget_Part_Impl (Gadget_ptr owner,
+ const char* name,
+ int size)
+ : owner_ (owner),
+ name_ (ACE::strnew (name)),
+ size_ (size)
+{
+ ACE_DEBUG ((LM_DEBUG, "Gadget_Part_Impl constructor\n"));
+}
+
+Gadget_Part_Impl::~Gadget_Part_Impl (void)
+{
+ ACE_DEBUG ((LM_DEBUG, "Gadget_Part_Impl destructor\n"));
+
+ delete [] name_;
+}
+
+void Gadget_Part_Impl::print_info (void)
+{
+ ACE_DEBUG ((LM_INFO, "Gadget part: name=%s size=%d\n", name_, size_));
+}
+
+void Gadget_Part_Impl::remove_from_owner (void)
+{
+ // Need to guarantee the existence of the owner for the duration of this call.
+ Gadget_var owner = owner_;
+
+ // Weak pointers are automatically set to NULL if the object they refer to
+ // is deleted. We can use this fact to check that our owner still exists.
+ if (owner == 0)
+ return;
+
+ // Take all existing parts from the owner and build up a temporary list. If
+ // we find ourselves then we won't add ourselves to the list.
+ ACE_Unbounded_Queue<Gadget_Part_var> parts;
+ for (;;)
+ {
+ Gadget_Part_var part = owner->remove_part ();
+ if (part == 0)
+ break;
+ if (part != this)
+ parts.enqueue_tail (part);
+ }
+
+ // Add the remaining parts back to the gadget.
+ while (!parts.is_empty ())
+ {
+ Gadget_Part_var part;
+ parts.dequeue_head (part);
+ owner->add_part (part);
+ }
+}
diff --git a/ACE/examples/Smart_Pointers/Gadget_Part_Impl.h b/ACE/examples/Smart_Pointers/Gadget_Part_Impl.h
new file mode 100644
index 00000000000..bcacb84f0c9
--- /dev/null
+++ b/ACE/examples/Smart_Pointers/Gadget_Part_Impl.h
@@ -0,0 +1,64 @@
+/* -*- C++ -*- */
+//=============================================================================
+/**
+ * @file Gadget_Part_Impl.h
+ *
+ * $Id$
+ *
+ * @author Christopher Kohlhoff <chris@kohlhoff.com>
+ */
+//=============================================================================
+
+#ifndef GADGET_PART_IMPL_H
+#define GADGET_PART_IMPL_H
+
+#include "Gadget_Part.h"
+#include "Gadget.h"
+
+/**
+ * @class Gadget_Part_Impl
+ *
+ * @brief An implementation of the Gadget_Part interface.
+ */
+class Gadget_Part_Impl : public Gadget_Part
+{
+public:
+ /// Constructor.
+ Gadget_Part_Impl (Gadget_ptr owner, const char* name, int size);
+
+ /// Destructor.
+ virtual ~Gadget_Part_Impl (void);
+
+ /// Ask the part to print information about itself.
+ virtual void print_info (void);
+
+ /// Ask the part to remove itself from the gadget that contains it.
+ virtual void remove_from_owner (void);
+
+private:
+ /// The gadget that contains this part.
+ ///
+ /// Some things to note about the choice of ACE_Weak_Bound_Ptr (from the
+ /// typedef for Gadget_ptr):
+ /// - We cannot use an ACE_Strong_Bound_Ptr (Gadget_var) since that would
+ /// result in circular ownership.
+ /// - If we use a raw pointer we have no circular ownership problems, but we
+ /// are unable to guarantee the lifetime of the owner object for the
+ /// duration of the remove_from_owner call. This may not be a problem in
+ /// this limited example, but in multithreaded programs remove_from_owner
+ /// may be called from a different thread to the thread which manages the
+ /// owner's lifetime.
+ /// - ACE_Weak_Bound_Ptr (Gadget_ptr) has no ownership semantics, so we have
+ /// no circular ownership problems. Weak pointers can also be converted
+ /// back into strong ones, so it is possible to guarantee the lifetime of
+ /// the owner object for the duration of the remove_from_owner call.
+ Gadget_ptr owner_;
+
+ /// The name of this part.
+ char *name_;
+
+ /// The size of this part.
+ int size_;
+};
+
+#endif /* GADGET_PART_IMPL_H */
diff --git a/ACE/examples/Smart_Pointers/Makefile.am b/ACE/examples/Smart_Pointers/Makefile.am
new file mode 100644
index 00000000000..4595d7dafaa
--- /dev/null
+++ b/ACE/examples/Smart_Pointers/Makefile.am
@@ -0,0 +1,70 @@
+## Process this file with automake to create Makefile.in
+##
+## $Id$
+##
+## This file was generated by MPC. Any changes made directly to
+## this file will be lost the next time it is generated.
+##
+## MPC Command:
+## /acebuilds/ACE_wrappers-repository/bin/mwc.pl -include /acebuilds/MPC/config -include /acebuilds/MPC/templates -feature_file /acebuilds/ACE_wrappers-repository/local.features -noreldefs -type automake -exclude build,Kokyu
+
+ACE_BUILDDIR = $(top_builddir)
+ACE_ROOT = $(top_srcdir)
+
+## Makefile.Smart_Pointers_Gadget.am
+noinst_PROGRAMS = gadget
+
+gadget_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+gadget_SOURCES = \
+ Gadget.cpp \
+ Gadget_Factory.cpp \
+ Gadget_Impl.cpp \
+ Gadget_Part.cpp \
+ Gadget_Part_Factory.cpp \
+ Gadget_Part_Impl.cpp \
+ gadget_test.cpp \
+ Gadget.h \
+ Gadget_Factory.h \
+ Gadget_Impl.h \
+ Gadget_Part.h \
+ Gadget_Part_Factory.h \
+ Gadget_Part_Impl.h
+
+gadget_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Makefile.Smart_Pointers_Widget.am
+noinst_PROGRAMS += Widget
+
+Widget_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+Widget_SOURCES = \
+ Widget.cpp \
+ Widget_Factory.cpp \
+ Widget_Impl.cpp \
+ Widget_Part.cpp \
+ Widget_Part_Factory.cpp \
+ Widget_Part_Impl.cpp \
+ widget_test.cpp \
+ Widget.h \
+ Widget_Factory.h \
+ Widget_Impl.h \
+ Widget_Part.h \
+ Widget_Part_Factory.h \
+ Widget_Part_Impl.h
+
+Widget_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Clean up template repositories, etc.
+clean-local:
+ -rm -f *~ *.bak *.rpo *.sym lib*.*_pure_* core core.*
+ -rm -f gcctemp.c gcctemp so_locations *.ics
+ -rm -rf cxx_repository ptrepository ti_files
+ -rm -rf templateregistry ir.out
+ -rm -rf ptrepository SunWS_cache Templates.DB
diff --git a/ACE/examples/Smart_Pointers/README b/ACE/examples/Smart_Pointers/README
new file mode 100644
index 00000000000..a23ea1eb828
--- /dev/null
+++ b/ACE/examples/Smart_Pointers/README
@@ -0,0 +1,29 @@
+$Id$
+
+Smart Pointers Example
+----------------------
+
+This example shows the use of the various smart pointer classes
+available in ACE.
+
+There are two programs in this example. Each program implements a
+similar set of classes, but with a different style of using smart
+pointers.
+
+The Widget example is written such that objects may only pass raw
+pointers between them, and use smart pointers to manage the object
+lifetimes. An advantage of this style is the fine-grained control
+over the type of smart pointer used in each situation. For example,
+if you know that in a particular section of code there is no
+concurrency involved, you can strategise ACE_Refcounted_Auto_Ptr on
+ACE_Null_Mutex to eliminate locking overhead. Disadvantages of this
+style include greater programming complexity and certain ownership
+use cases not being easily supported.
+
+The Gadget example is written such that objects are always passed
+around using one of the ACE_Strong_Bound_Ptr/ACE_Weak_Bound_Ptr
+pair of smart pointers. The advantage of this style is the
+reduction in complexity of object lifetime management (almost as
+"good" as Java ;-) The disadvantage is that you pay a cost for the
+reference counting and locking overhead even in situations where it
+may not be strictly necessary.
diff --git a/ACE/examples/Smart_Pointers/Smart_Pointers.mpc b/ACE/examples/Smart_Pointers/Smart_Pointers.mpc
new file mode 100644
index 00000000000..fc2fc781a78
--- /dev/null
+++ b/ACE/examples/Smart_Pointers/Smart_Pointers.mpc
@@ -0,0 +1,28 @@
+// -*- MPC -*-
+// $Id$
+
+project(*Gadget) : aceexe {
+ exename = gadget
+ Source_Files {
+ Gadget.cpp
+ Gadget_Factory.cpp
+ Gadget_Impl.cpp
+ Gadget_Part.cpp
+ Gadget_Part_Factory.cpp
+ Gadget_Part_Impl.cpp
+ gadget_test.cpp
+ }
+}
+
+project(*Widget) : aceexe {
+ exename = Widget
+ Source_Files {
+ Widget.cpp
+ Widget_Factory.cpp
+ Widget_Impl.cpp
+ Widget_Part.cpp
+ Widget_Part_Factory.cpp
+ Widget_Part_Impl.cpp
+ widget_test.cpp
+ }
+}
diff --git a/ACE/examples/Smart_Pointers/Widget.cpp b/ACE/examples/Smart_Pointers/Widget.cpp
new file mode 100644
index 00000000000..28d01b54461
--- /dev/null
+++ b/ACE/examples/Smart_Pointers/Widget.cpp
@@ -0,0 +1,16 @@
+/* -*- C++ -*- */
+//=============================================================================
+/**
+ * @file Widget.cpp
+ *
+ * $Id$
+ *
+ * @author Christopher Kohlhoff <chris@kohlhoff.com>
+ */
+//=============================================================================
+
+#include "Widget.h"
+
+Widget::~Widget (void)
+{
+}
diff --git a/ACE/examples/Smart_Pointers/Widget.h b/ACE/examples/Smart_Pointers/Widget.h
new file mode 100644
index 00000000000..a38245ca999
--- /dev/null
+++ b/ACE/examples/Smart_Pointers/Widget.h
@@ -0,0 +1,40 @@
+/* -*- C++ -*- */
+//=============================================================================
+/**
+ * @file Widget.h
+ *
+ * $Id$
+ *
+ * @author Christopher Kohlhoff <chris@kohlhoff.com>
+ */
+//=============================================================================
+
+#ifndef WIDGET_H
+#define WIDGET_H
+
+#include "Widget_Part.h"
+
+/**
+ * @class Widget
+ *
+ * @brief An interface for some high-level application object.
+ */
+class Widget
+{
+public:
+ /// Destructor.
+ virtual ~Widget (void);
+
+ /// Add a new part to the widget. The widget takes ownership of the part
+ /// object.
+ virtual void add_part (Widget_Part *part) = 0;
+
+ /// Remove a random part from the widget. Ownership of the part is returned
+ /// to the caller.
+ virtual Widget_Part *remove_part (void) = 0;
+
+ /// Ask the widget to print information about the parts that it contains.
+ virtual void list_parts (void) = 0;
+};
+
+#endif /* WIDGET_H */
diff --git a/ACE/examples/Smart_Pointers/Widget_Factory.cpp b/ACE/examples/Smart_Pointers/Widget_Factory.cpp
new file mode 100644
index 00000000000..18fec0c23f4
--- /dev/null
+++ b/ACE/examples/Smart_Pointers/Widget_Factory.cpp
@@ -0,0 +1,18 @@
+/* -*- C++ -*- */
+//=============================================================================
+/**
+ * @file Widget_Factory.cpp
+ *
+ * $Id$
+ *
+ * @author Christopher Kohlhoff <chris@kohlhoff.com>
+ */
+//=============================================================================
+
+#include "Widget_Factory.h"
+#include "Widget_Impl.h"
+
+Widget *Widget_Factory::create_widget (void)
+{
+ return new Widget_Impl;
+}
diff --git a/ACE/examples/Smart_Pointers/Widget_Factory.h b/ACE/examples/Smart_Pointers/Widget_Factory.h
new file mode 100644
index 00000000000..adf0613a3fe
--- /dev/null
+++ b/ACE/examples/Smart_Pointers/Widget_Factory.h
@@ -0,0 +1,30 @@
+/* -*- C++ -*- */
+//=============================================================================
+/**
+ * @file Widget_Factory.h
+ *
+ * $Id$
+ *
+ * @author Christopher Kohlhoff <chris@kohlhoff.com>
+ */
+//=============================================================================
+
+#ifndef WIDGET_FACTORY_H
+#define WIDGET_FACTORY_H
+
+#include "Widget.h"
+
+/**
+ * @class Widget_Factory
+ *
+ * @brief Used to create Widget instances.
+ */
+class Widget_Factory
+{
+public:
+ /// Create an instance of a widget. Ownership of the newly created object is
+ /// transferred to the caller.
+ static Widget *create_widget (void);
+};
+
+#endif /* WIDGET_FACTORY_H */
diff --git a/ACE/examples/Smart_Pointers/Widget_Impl.cpp b/ACE/examples/Smart_Pointers/Widget_Impl.cpp
new file mode 100644
index 00000000000..2d3ab404804
--- /dev/null
+++ b/ACE/examples/Smart_Pointers/Widget_Impl.cpp
@@ -0,0 +1,52 @@
+/* -*- C++ -*- */
+//=============================================================================
+/**
+ * @file Widget_Impl.cpp
+ *
+ * $Id$
+ *
+ * @author Christopher Kohlhoff <chris@kohlhoff.com>
+ */
+//=============================================================================
+
+#include "Widget_Impl.h"
+#include "ace/Log_Msg.h"
+
+Widget_Impl::Widget_Impl (void)
+{
+ ACE_DEBUG ((LM_DEBUG, "Widget_Impl constructor\n"));
+}
+
+Widget_Impl::~Widget_Impl (void)
+{
+ ACE_DEBUG ((LM_DEBUG, "Widget_Impl destructor\n"));
+}
+
+void Widget_Impl::add_part (Widget_Part *part)
+{
+ // Take ownership of the part object using a ACE_Refcounted_Auto_Ptr.
+ ACE_Refcounted_Auto_Ptr<Widget_Part, ACE_SYNCH_MUTEX> new_part (part);
+
+ parts_.enqueue_tail (new_part);
+}
+
+Widget_Part *Widget_Impl::remove_part (void)
+{
+ ACE_Refcounted_Auto_Ptr<Widget_Part, ACE_SYNCH_MUTEX> removed_part;
+ if (parts_.dequeue_head (removed_part) == -1)
+ return 0;
+
+ // Ownership of the part object is released and transferred to the caller.
+ return removed_part.release();
+}
+
+void Widget_Impl::list_parts (void)
+{
+ ACE_Unbounded_Queue_Iterator<ACE_Refcounted_Auto_Ptr<Widget_Part, ACE_SYNCH_MUTEX> > iter (parts_);
+ ACE_Refcounted_Auto_Ptr<Widget_Part, ACE_SYNCH_MUTEX> *current_part;
+ while (iter.next (current_part))
+ {
+ (*current_part)->print_info ();
+ iter.advance ();
+ }
+}
diff --git a/ACE/examples/Smart_Pointers/Widget_Impl.h b/ACE/examples/Smart_Pointers/Widget_Impl.h
new file mode 100644
index 00000000000..4933841f912
--- /dev/null
+++ b/ACE/examples/Smart_Pointers/Widget_Impl.h
@@ -0,0 +1,68 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file Widget_Impl.h
+ *
+ * $Id$
+ *
+ * @author Christopher Kohlhoff <chris@kohlhoff.com>
+ */
+//=============================================================================
+
+#ifndef WIDGET_IMPL_H
+#define WIDGET_IMPL_H
+
+#include "Widget.h"
+#include "Widget_Part.h"
+
+#include "ace/Unbounded_Queue.h"
+#include "ace/Refcounted_Auto_Ptr.h"
+#include "ace/Synch_Traits.h"
+#include "ace/Thread_Mutex.h"
+
+/**
+ * @class Widget_Impl
+ *
+ * @brief An implementation of the Widget interface.
+ */
+class Widget_Impl : public Widget
+{
+public:
+ /// Constructor.
+ Widget_Impl (void);
+
+ /// Destructor.
+ virtual ~Widget_Impl (void);
+
+ /// Add a new part to the widget. The widget takes ownership of the part
+ /// object.
+ virtual void add_part (Widget_Part *part);
+
+ /// Remove a random part from the widget. Ownership of the part is returned
+ /// to the caller.
+ virtual Widget_Part *remove_part (void);
+
+ /// Ask the widget to print information about the parts that it contains.
+ virtual void list_parts (void);
+
+private:
+ /// The parts which make up this widget. The set actually contains instances
+ /// of ACE_Refcounted_Auto_Ptr to automatically manage the lifetimes of the
+ /// constituent parts.
+ ///
+ /// Some things to note about the choice of ACE_Refcounted_Auto_Ptr:
+ /// - We cannot use auto_ptr to manage the objects, since auto_ptr does not
+ /// support the copying and assignment semantics necessary for storage in
+ /// a container.
+ /// - The ACE_Strong_Bound_Ptr reference counted pointer could be used to
+ /// store objects in a container, however (for reasons of safety) it
+ /// provides no way to release ownership of the object from the smart
+ /// pointer. We need to be able to release ownership to implement the
+ /// remove_part method.
+ /// - ACE_Refcounted_Ptr can both be stored in containers and allows us to
+ /// release ownership of the pointer that it contains.
+ ACE_Unbounded_Queue<ACE_Refcounted_Auto_Ptr<Widget_Part, ACE_SYNCH_MUTEX> > parts_;
+};
+
+#endif /* WIDGET_IMPL_H */
diff --git a/ACE/examples/Smart_Pointers/Widget_Part.cpp b/ACE/examples/Smart_Pointers/Widget_Part.cpp
new file mode 100644
index 00000000000..7a74447cff9
--- /dev/null
+++ b/ACE/examples/Smart_Pointers/Widget_Part.cpp
@@ -0,0 +1,16 @@
+/* -*- C++ -*- */
+//=============================================================================
+/**
+ * @file Widget_Part.cpp
+ *
+ * $Id$
+ *
+ * @author Christopher Kohlhoff <chris@kohlhoff.com>
+ */
+//=============================================================================
+
+#include "Widget_Part.h"
+
+Widget_Part::~Widget_Part (void)
+{
+}
diff --git a/ACE/examples/Smart_Pointers/Widget_Part.h b/ACE/examples/Smart_Pointers/Widget_Part.h
new file mode 100644
index 00000000000..7e1f0b575a9
--- /dev/null
+++ b/ACE/examples/Smart_Pointers/Widget_Part.h
@@ -0,0 +1,33 @@
+/* -*- C++ -*- */
+//=============================================================================
+/**
+ * @file Widget_Part.h
+ *
+ * $Id$
+ *
+ * @author Christopher Kohlhoff <chris@kohlhoff.com>
+ */
+//=============================================================================
+
+#ifndef WIDGET_PART_H
+#define WIDGET_PART_H
+
+/**
+ * @class Widget_Part
+ *
+ * @brief An interface for some high-level application object.
+ */
+class Widget_Part
+{
+public:
+ /// Destructor.
+ virtual ~Widget_Part (void);
+
+ /// Ask the part to print information about itself.
+ virtual void print_info (void) = 0;
+
+ /// Ask the part to remove itself from the widget that contains it.
+ virtual void remove_from_owner (void) = 0;
+};
+
+#endif /* WIDGET_PART_H */
diff --git a/ACE/examples/Smart_Pointers/Widget_Part_Factory.cpp b/ACE/examples/Smart_Pointers/Widget_Part_Factory.cpp
new file mode 100644
index 00000000000..501cdbc745c
--- /dev/null
+++ b/ACE/examples/Smart_Pointers/Widget_Part_Factory.cpp
@@ -0,0 +1,20 @@
+/* -*- C++ -*- */
+//=============================================================================
+/**
+ * @file Widget_Part_Factory.cpp
+ *
+ * $Id$
+ *
+ * @author Christopher Kohlhoff <chris@kohlhoff.com>
+ */
+//=============================================================================
+
+#include "Widget_Part_Factory.h"
+#include "Widget_Part_Impl.h"
+
+Widget_Part *Widget_Part_Factory::create_widget_part (Widget *owner,
+ const char* name,
+ int size)
+{
+ return new Widget_Part_Impl (owner, name, size);
+}
diff --git a/ACE/examples/Smart_Pointers/Widget_Part_Factory.h b/ACE/examples/Smart_Pointers/Widget_Part_Factory.h
new file mode 100644
index 00000000000..4902ab91c40
--- /dev/null
+++ b/ACE/examples/Smart_Pointers/Widget_Part_Factory.h
@@ -0,0 +1,31 @@
+/* -*- C++ -*- */
+//=============================================================================
+/**
+ * @file Widget_Part_Factory.h
+ *
+ * $Id$
+ *
+ * @author Christopher Kohlhoff <chris@kohlhoff.com>
+ */
+//=============================================================================
+
+#ifndef WIDGET_PART_FACTORY_H
+#define WIDGET_PART_FACTORY_H
+
+#include "Widget_Part.h"
+#include "Widget.h"
+
+/**
+ * @class Widget_Part_Factory
+ *
+ * @brief Used to create Widget_Part instances.
+ */
+class Widget_Part_Factory
+{
+public:
+ /// Create an instance of a widget part. Ownership of the newly created
+ /// object is transferred to the caller.
+ static Widget_Part *create_widget_part (Widget *owner, const char *name, int size);
+};
+
+#endif /* WIDGET_PART_FACTORY_H */
diff --git a/ACE/examples/Smart_Pointers/Widget_Part_Impl.cpp b/ACE/examples/Smart_Pointers/Widget_Part_Impl.cpp
new file mode 100644
index 00000000000..0e4e496f180
--- /dev/null
+++ b/ACE/examples/Smart_Pointers/Widget_Part_Impl.cpp
@@ -0,0 +1,74 @@
+/* -*- C++ -*- */
+//=============================================================================
+/**
+ * @file Widget_Part_Impl.cpp
+ *
+ * $Id$
+ *
+ * @author Christopher Kohlhoff <chris@kohlhoff.com>
+ */
+//=============================================================================
+
+#include "Widget_Part_Impl.h"
+#include "ace/ACE.h"
+#include "ace/Log_Msg.h"
+#include "ace/Refcounted_Auto_Ptr.h"
+#include "ace/Unbounded_Queue.h"
+#include "ace/Null_Mutex.h"
+
+Widget_Part_Impl::Widget_Part_Impl (Widget *owner, const char* name, int size)
+ : owner_ (owner),
+ name_ (ACE::strnew (name)),
+ size_ (size)
+{
+ ACE_DEBUG ((LM_DEBUG, "Widget_Part_Impl constructor\n"));
+}
+
+Widget_Part_Impl::~Widget_Part_Impl (void)
+{
+ ACE_DEBUG ((LM_DEBUG, "Widget_Part_Impl destructor\n"));
+
+ delete [] name_;
+}
+
+void Widget_Part_Impl::print_info (void)
+{
+ ACE_DEBUG ((LM_INFO, "Widget part: name=%s size=%d\n", name_, size_));
+}
+
+void Widget_Part_Impl::remove_from_owner (void)
+{
+ // Since we only have a raw pointer to refer to the owner, we have no way of
+ // checking whether the owner still exists, and if it does guaranteeing that
+ // it will continue to exist for the duration of this call. This is not an
+ // issue in this limited example program, but in multithreaded applications
+ // this function may be called from a different thread to that managing the
+ // lifetime of the owner object. See the Gadget example for how
+ // ACE_Strong_Bound_Ptr/ACE_Weak_Bound_Ptr can be used to address the problem.
+
+ // Take all existing parts from the owner and build up a temporary queue. If
+ // we find ourselves then we won't add ourselves to the queue. We will
+ // actually store ACE_Refcounted_Auto_Ptr instances in the queue, and since we
+ // know that there is only one thread involved we can use ACE_Null_Mutex to
+ // eliminate the locking overhead.
+ ACE_Unbounded_Queue<ACE_Refcounted_Auto_Ptr<Widget_Part, ACE_Null_Mutex> > parts;
+ for (;;)
+ {
+ ACE_Refcounted_Auto_Ptr<Widget_Part, ACE_Null_Mutex> part (owner_->remove_part ());
+ if (part.null ())
+ break;
+ if (part.get () == this)
+ // Someone else will be responsible for our lifetime.
+ part.release();
+ else
+ parts.enqueue_tail (part);
+ }
+
+ // Add the remaining parts back to the gadget.
+ while (!parts.is_empty ())
+ {
+ ACE_Refcounted_Auto_Ptr<Widget_Part, ACE_Null_Mutex> part;
+ parts.dequeue_head (part);
+ owner_->add_part (part.release ());
+ }
+}
diff --git a/ACE/examples/Smart_Pointers/Widget_Part_Impl.h b/ACE/examples/Smart_Pointers/Widget_Part_Impl.h
new file mode 100644
index 00000000000..dbb1d4c714c
--- /dev/null
+++ b/ACE/examples/Smart_Pointers/Widget_Part_Impl.h
@@ -0,0 +1,49 @@
+/* -*- C++ -*- */
+//=============================================================================
+/**
+ * @file Widget_Part_Impl.h
+ *
+ * $Id$
+ *
+ * @author Christopher Kohlhoff <chris@kohlhoff.com>
+ */
+//=============================================================================
+
+#ifndef WIDGET_PART_IMPL_H
+#define WIDGET_PART_IMPL_H
+
+#include "Widget_Part.h"
+#include "Widget.h"
+
+/**
+ * @class Widget_Part_Impl
+ *
+ * @brief An implementation of the Widget_Part interface.
+ */
+class Widget_Part_Impl : public Widget_Part
+{
+public:
+ /// Constructor.
+ Widget_Part_Impl (Widget *owner, const char* name, int size);
+
+ /// Destructor.
+ virtual ~Widget_Part_Impl (void);
+
+ /// Ask the part to print information about itself.
+ virtual void print_info (void);
+
+ /// Ask the part to remove itself from the widget that contains it.
+ virtual void remove_from_owner (void);
+
+private:
+ /// The widget that contains this part.
+ Widget *owner_;
+
+ /// The name of this part.
+ char *name_;
+
+ /// The size of this part.
+ int size_;
+};
+
+#endif /* WIDGET_PART_IMPL_H */
diff --git a/ACE/examples/Smart_Pointers/gadget_test.cpp b/ACE/examples/Smart_Pointers/gadget_test.cpp
new file mode 100644
index 00000000000..94c17b2a556
--- /dev/null
+++ b/ACE/examples/Smart_Pointers/gadget_test.cpp
@@ -0,0 +1,52 @@
+/* -*- C++ -*- */
+//=============================================================================
+/**
+ * @file gadget_test.cpp
+ *
+ * $Id$
+ *
+ * @author Christopher Kohlhoff <chris@kohlhoff.com>
+ */
+//=============================================================================
+
+#include "ace/Auto_Ptr.h"
+#include "ace/Refcounted_Auto_Ptr.h"
+#include "ace/Unbounded_Queue.h"
+#include "Gadget.h"
+#include "Gadget_Factory.h"
+#include "Gadget_Part.h"
+#include "Gadget_Part_Factory.h"
+
+int ACE_TMAIN (int argc, ACE_TCHAR *argv[])
+{
+ ACE_UNUSED_ARG (argc);
+ ACE_UNUSED_ARG (argv);
+
+ Gadget_var g1 = Gadget_Factory::create_gadget ();
+ g1->add_part (Gadget_Part_Factory::create_gadget_part (g1, "part1", 1));
+ g1->add_part (Gadget_Part_Factory::create_gadget_part (g1, "part2", 2));
+ g1->add_part (Gadget_Part_Factory::create_gadget_part (g1, "part3", 3));
+
+ g1->list_parts ();
+
+ Gadget_Part_var p1 = g1->remove_part ();
+ p1->print_info ();
+
+ // Oops, we forgot to collect the return value! No worries, the temporary
+ // Gadget_var returned by the function call will clean it up automatically.
+ g1->remove_part ();
+
+ g1->list_parts ();
+
+ Gadget_var g2 = Gadget_Factory::create_gadget ();
+ g2->add_part (Gadget_Part_Factory::create_gadget_part (g2, "part4", 4));
+ Gadget_Part_var p2 = Gadget_Part_Factory::create_gadget_part (g2, "part5", 5);
+ g2->add_part (p2);
+ p2->remove_from_owner ();
+
+ g2->list_parts ();
+
+ return 0;
+}
+
+
diff --git a/ACE/examples/Smart_Pointers/widget_test.cpp b/ACE/examples/Smart_Pointers/widget_test.cpp
new file mode 100644
index 00000000000..4fc8b5824a2
--- /dev/null
+++ b/ACE/examples/Smart_Pointers/widget_test.cpp
@@ -0,0 +1,51 @@
+/* -*- C++ -*- */
+//=============================================================================
+/**
+ * @file widget_test.cpp
+ *
+ * $Id$
+ *
+ * @author Christopher Kohlhoff <chris@kohlhoff.com>
+ */
+//=============================================================================
+
+#include "ace/Auto_Ptr.h"
+#include "ace/Refcounted_Auto_Ptr.h"
+#include "ace/Unbounded_Queue.h"
+#include "ace/Synch_Traits.h"
+#include "ace/Thread_Mutex.h"
+#include "ace/Null_Mutex.h"
+#include "Widget.h"
+#include "Widget_Factory.h"
+#include "Widget_Part.h"
+#include "Widget_Part_Factory.h"
+
+int ACE_TMAIN (int argc, ACE_TCHAR *argv[])
+{
+ ACE_UNUSED_ARG (argc);
+ ACE_UNUSED_ARG (argv);
+
+ auto_ptr<Widget> w1 (Widget_Factory::create_widget ());
+ w1->add_part (Widget_Part_Factory::create_widget_part (w1.get(), "part1", 1));
+ w1->add_part (Widget_Part_Factory::create_widget_part (w1.get(), "part2", 2));
+ w1->add_part (Widget_Part_Factory::create_widget_part (w1.get(), "part3", 3));
+
+ w1->list_parts ();
+
+ auto_ptr<Widget_Part> p1 (w1->remove_part ());
+ p1->print_info ();
+ auto_ptr<Widget_Part> p2 (w1->remove_part ());
+
+ w1->list_parts ();
+
+ auto_ptr<Widget> w2 (Widget_Factory::create_widget ());
+ w2->add_part (Widget_Part_Factory::create_widget_part (w2.get(), "part4", 4));
+ Widget_Part *p3 = Widget_Part_Factory::create_widget_part (w2.get(), "part5", 5);
+ w2->add_part (p3);
+ p3->remove_from_owner ();
+
+ w2->list_parts ();
+
+ return 0;
+}
+
diff --git a/ACE/examples/Synch/.cvsignore b/ACE/examples/Synch/.cvsignore
new file mode 100644
index 00000000000..eea98594a4b
--- /dev/null
+++ b/ACE/examples/Synch/.cvsignore
@@ -0,0 +1 @@
+proc_sema
diff --git a/ACE/examples/Synch/Makefile.am b/ACE/examples/Synch/Makefile.am
new file mode 100644
index 00000000000..09319f393b3
--- /dev/null
+++ b/ACE/examples/Synch/Makefile.am
@@ -0,0 +1,38 @@
+## Process this file with automake to create Makefile.in
+##
+## $Id$
+##
+## This file was generated by MPC. Any changes made directly to
+## this file will be lost the next time it is generated.
+##
+## MPC Command:
+## /acebuilds/ACE_wrappers-repository/bin/mwc.pl -include /acebuilds/MPC/config -include /acebuilds/MPC/templates -feature_file /acebuilds/ACE_wrappers-repository/local.features -noreldefs -type automake -exclude build,Kokyu
+
+ACE_BUILDDIR = $(top_builddir)
+ACE_ROOT = $(top_srcdir)
+
+
+## Makefile.Synch.am
+
+if !BUILD_ACE_FOR_TAO
+noinst_PROGRAMS = proc_sema
+
+proc_sema_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+proc_sema_SOURCES = \
+ proc_sema.cpp
+
+proc_sema_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+endif !BUILD_ACE_FOR_TAO
+
+## Clean up template repositories, etc.
+clean-local:
+ -rm -f *~ *.bak *.rpo *.sym lib*.*_pure_* core core.*
+ -rm -f gcctemp.c gcctemp so_locations *.ics
+ -rm -rf cxx_repository ptrepository ti_files
+ -rm -rf templateregistry ir.out
+ -rm -rf ptrepository SunWS_cache Templates.DB
diff --git a/ACE/examples/Synch/README b/ACE/examples/Synch/README
new file mode 100644
index 00000000000..526120f2744
--- /dev/null
+++ b/ACE/examples/Synch/README
@@ -0,0 +1,21 @@
+This directory currently only contains one example for testing process
+semaphores.
+
+proc_sema:
+ This test can be used to test out the named process semaphores
+support on your platform. It can be run as either a supplier or a
+consumer process. The available options are:
+
+ -c: Make us a consumer.
+ -s: Make us a supplier.
+ -x: Remove the semaphore after we're done.
+ -n: Specify the name of the semaphore.
+ -i: Number of acquire/release we'll perform.
+ -d: Delay for # of second before exiting the program
+
+ You can use this test to see how process semaphores work. For
+example, run the program as:
+
+ proc_sema -c -i 10
+ proc_sema -s -i 3
+ proc_sema -s -i 7
diff --git a/ACE/examples/Synch/Synch.mpc b/ACE/examples/Synch/Synch.mpc
new file mode 100644
index 00000000000..024e8459803
--- /dev/null
+++ b/ACE/examples/Synch/Synch.mpc
@@ -0,0 +1,7 @@
+// -*- MPC -*-
+// $Id$
+
+project : aceexe {
+ avoids += ace_for_tao
+ exename = proc_sema
+}
diff --git a/ACE/examples/Synch/proc_sema.cpp b/ACE/examples/Synch/proc_sema.cpp
new file mode 100644
index 00000000000..d9da687ca6a
--- /dev/null
+++ b/ACE/examples/Synch/proc_sema.cpp
@@ -0,0 +1,98 @@
+// $Id$
+
+#include "ace/OS_main.h"
+#include "ace/Process_Semaphore.h"
+#include "ace/Get_Opt.h"
+#include "ace/Log_Msg.h"
+#include "ace/OS_NS_stdlib.h"
+#include "ace/OS_NS_unistd.h"
+#include "ace/Synch_Traits.h"
+
+int producer (ACE_SYNCH_PROCESS_SEMAPHORE &sema,
+ int iter)
+{
+ for (int i = iter; i > 0; --i)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ "Try releasing the semaphore (%d): ",
+ i));
+
+ int result = sema.release ();
+
+ ACE_DEBUG ((LM_DEBUG,
+ "%s",
+ (result != 0 ? "fail\n" : "succeed\n")));
+ }
+ return 0;
+}
+
+int consumer (ACE_SYNCH_PROCESS_SEMAPHORE &sema,
+ int iter)
+{
+ for (int i = iter; i > 0; --i)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ "Try acquiring the semaphore (%d): ",
+ i));
+
+ int result = sema.acquire ();
+
+ ACE_DEBUG ((LM_DEBUG,
+ "%s",
+ (result != 0 ? "fail\n" : "succeed\n")));
+ }
+ return 0;
+}
+
+int ACE_TMAIN (int argc, ACE_TCHAR *argv[])
+{
+ ACE_Get_Opt getopt (argc, argv, ACE_TEXT ("csn:xi:d:"));
+
+ int is_consumer = 1; // By default, make us a consumer.
+ int delete_sema = 0;
+ int iteration = 0;
+ int exit_delay = 0;
+ const ACE_TCHAR *sema_name = ACE_TEXT ("Process_Semaphore_Test");
+
+ int opt;
+
+ while ((opt = getopt ()) != -1)
+ {
+ switch (opt)
+ {
+ case 'c': // Make us a consumer.
+ is_consumer = 1;
+ break;
+ case 's': // Make us a supplier.
+ is_consumer = 0;
+ break;
+ case 'x': // Remove the semaphore after we're done.
+ delete_sema = 1;
+ break;
+ case 'n': // Specify the name of the semaphore.
+ sema_name = getopt.opt_arg ();
+ break;
+ case 'i': // Number of acquire/release we'll perform.
+ iteration = ACE_OS::atoi (getopt.opt_arg ());
+ break;
+ case 'd':
+ exit_delay = ACE_OS::atoi (getopt.opt_arg ());
+ break;
+ default:
+ return -1;
+ }
+ };
+
+ ACE_SYNCH_PROCESS_SEMAPHORE sema (0, sema_name);
+
+ if (is_consumer != 0)
+ consumer (sema, iteration);
+ else
+ producer (sema, iteration);
+
+ ACE_OS::sleep (exit_delay);
+
+ if (delete_sema != 0)
+ sema.remove ();
+ return 0;
+}
diff --git a/ACE/examples/System_V_IPC/Makefile.am b/ACE/examples/System_V_IPC/Makefile.am
new file mode 100644
index 00000000000..23b52ee8b29
--- /dev/null
+++ b/ACE/examples/System_V_IPC/Makefile.am
@@ -0,0 +1,14 @@
+## Process this file with automake to create Makefile.in
+##
+## $Id$
+##
+## This file was generated by MPC. Any changes made directly to
+## this file will be lost the next time it is generated.
+##
+## MPC Command:
+## /acebuilds/ACE_wrappers-repository/bin/mwc.pl -include /acebuilds/MPC/config -include /acebuilds/MPC/templates -feature_file /acebuilds/ACE_wrappers-repository/local.features -noreldefs -type automake -exclude build,Kokyu
+
+SUBDIRS = \
+ SV_Message_Queues \
+ SV_Semaphores
+
diff --git a/ACE/examples/System_V_IPC/README b/ACE/examples/System_V_IPC/README
new file mode 100644
index 00000000000..c5ebde21a60
--- /dev/null
+++ b/ACE/examples/System_V_IPC/README
@@ -0,0 +1,13 @@
+This directory contains a number of examples that illustrate how to
+use the following ACE library components:
+
+ . SV_Message_Queues
+ Illustrates the ACE wrappers for System V Message
+ Queues.
+
+ . SV_Semaphores
+ Illustrates the ACE wrappers for System V Semaphores.
+
+ . SV_Shared_Memory
+ Illustrates the ACE wrappers for System V Shared Memory.
+
diff --git a/ACE/examples/System_V_IPC/SV_Message_Queues/.cvsignore b/ACE/examples/System_V_IPC/SV_Message_Queues/.cvsignore
new file mode 100644
index 00000000000..bcdb18d69d8
--- /dev/null
+++ b/ACE/examples/System_V_IPC/SV_Message_Queues/.cvsignore
@@ -0,0 +1,4 @@
+mqclient
+mqserver
+tmqclient
+tmqserver
diff --git a/ACE/examples/System_V_IPC/SV_Message_Queues/MQ_Client.cpp b/ACE/examples/System_V_IPC/SV_Message_Queues/MQ_Client.cpp
new file mode 100644
index 00000000000..547e4175121
--- /dev/null
+++ b/ACE/examples/System_V_IPC/SV_Message_Queues/MQ_Client.cpp
@@ -0,0 +1,55 @@
+// $Id$
+
+#include "ace/SV_Message_Queue.h"
+#include "test.h"
+
+// FUZZ: disable check_for_streams_include
+#include "ace/streams.h"
+
+#include "ace/Malloc.h"
+#include "ace/OS_NS_stdio.h"
+#include "ace/OS_NS_unistd.h"
+#include "ace/OS_NS_stdlib.h"
+
+ACE_RCSID(SV_Message_Queues, MQ_Client, "$Id$")
+
+#if defined (ACE_HAS_SYSV_IPC) && !defined(ACE_LACKS_SYSV_SHMEM)
+
+int
+main (int, char *[])
+{
+ long pid = long (ACE_OS::getpid ());
+ ACE_SV_Message_Queue msgque (SRV_KEY);
+ Message_Block send_msg (SRV_ID,
+ pid,
+ ACE_OS::cuserid (static_cast<char *> (0)),
+ "did you get this?");
+ Message_Block recv_msg (pid);
+
+ if (msgque.send (send_msg, send_msg.length ()) < 0)
+ ACE_OS::perror ("msgque.send"), ACE_OS::exit (1);
+
+ if (msgque.recv (recv_msg, sizeof (Message_Data), recv_msg.type ()) < 0)
+ ACE_OS::perror ("msgrcv"), ACE_OS::exit (1);
+
+ cout << "a message of length "
+ << recv_msg.length ()
+ << " received from server "
+ << recv_msg.pid ()
+ << " (user "
+ << recv_msg.user () << "): "
+ << recv_msg.text () << "\n";
+
+ return 0;
+}
+
+#else
+
+int ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ ACE_ERROR ((LM_ERROR,
+ "SYSV IPC, or SYSV SHMEM is not supported on this platform\n"));
+ return 0;
+}
+#endif /* ACE_HAS_SYSV_IPC && !ACE_LACKS_SYSV_SHMEM*/
+
diff --git a/ACE/examples/System_V_IPC/SV_Message_Queues/MQ_Server.cpp b/ACE/examples/System_V_IPC/SV_Message_Queues/MQ_Server.cpp
new file mode 100644
index 00000000000..33761465813
--- /dev/null
+++ b/ACE/examples/System_V_IPC/SV_Message_Queues/MQ_Server.cpp
@@ -0,0 +1,81 @@
+// $Id$
+
+#include "ace/Signal.h"
+#include "ace/SV_Message_Queue.h"
+
+// FUZZ: disable check_for_streams_include
+#include "ace/streams.h"
+
+#include "test.h"
+#include "ace/OS_NS_stdio.h"
+#include "ace/OS_NS_unistd.h"
+#include "ace/OS_NS_stdlib.h"
+
+ACE_RCSID(SV_Message_Queues, MQ_Server, "$Id$")
+
+#if defined (ACE_HAS_SYSV_IPC) && !defined(ACE_LACKS_SYSV_SHMEM)
+
+// Must be global for signal Message...
+static ACE_SV_Message_Queue ace_sv_message_queue (SRV_KEY,
+ ACE_SV_Message_Queue::ACE_CREATE);
+
+extern "C" void
+handler (int)
+{
+ if (ace_sv_message_queue.remove () < 0)
+ ACE_OS::perror ("ace_sv_message_queue.close"), ACE_OS::exit (1);
+ ACE_OS::exit (0);
+}
+
+int
+main (int, char *[])
+{
+ long pid = long (ACE_OS::getpid ());
+ Message_Block recv_msg (SRV_ID);
+ Message_Block send_msg (0,
+ pid,
+ ACE_OS::cuserid (static_cast<char *> (0)),
+ "I received your message.");
+
+ // Register a signal handler.
+ ACE_Sig_Action sa ((ACE_SignalHandler) handler, SIGINT);
+ ACE_UNUSED_ARG (sa);
+
+ for (;;)
+ {
+ if (ace_sv_message_queue.recv (recv_msg,
+ sizeof (Message_Data),
+ recv_msg.type ()) == -1)
+ ::perror ("ace_sv_message_queue.recv"), ACE_OS::exit (1);
+
+ cout << "a msg of length "
+ << recv_msg.length ()
+ << " sent from client "
+ << recv_msg.pid ()
+ << " (user "
+ << recv_msg.user () << "): "
+ << recv_msg.text () << "\n";
+
+ cout.flush ();
+
+ send_msg.type (recv_msg.pid ());
+
+ if (ace_sv_message_queue.send (send_msg,
+ send_msg.length ()) == -1)
+ ACE_OS::perror ("ace_sv_message_queue.send"), ACE_OS::exit (1);
+ }
+
+ ACE_NOTREACHED (return 0;)
+}
+
+#else
+
+#include "ace/Log_Msg.h"
+
+int ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ ACE_ERROR ((LM_ERROR,
+ "SYSV IPC, or SYSV SHMEM is not supported on this platform\n"));
+ return 0;
+}
+#endif /* ACE_HAS_SYSV_IPC && !ACE_LACKS_SYSV_SHMEM */
diff --git a/ACE/examples/System_V_IPC/SV_Message_Queues/Makefile.am b/ACE/examples/System_V_IPC/SV_Message_Queues/Makefile.am
new file mode 100644
index 00000000000..eadb6b8df53
--- /dev/null
+++ b/ACE/examples/System_V_IPC/SV_Message_Queues/Makefile.am
@@ -0,0 +1,94 @@
+## Process this file with automake to create Makefile.in
+##
+## $Id$
+##
+## This file was generated by MPC. Any changes made directly to
+## this file will be lost the next time it is generated.
+##
+## MPC Command:
+## /acebuilds/ACE_wrappers-repository/bin/mwc.pl -include /acebuilds/MPC/config -include /acebuilds/MPC/templates -feature_file /acebuilds/ACE_wrappers-repository/local.features -noreldefs -type automake -exclude build,Kokyu
+
+ACE_BUILDDIR = $(top_builddir)
+ACE_ROOT = $(top_srcdir)
+
+noinst_PROGRAMS =
+
+## Makefile.SV_Message_Queues_MQ_Client.am
+
+if !BUILD_ACE_FOR_TAO
+noinst_PROGRAMS += mqclient
+
+mqclient_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+mqclient_SOURCES = \
+ MQ_Client.cpp \
+ test.h
+
+mqclient_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+endif !BUILD_ACE_FOR_TAO
+
+## Makefile.SV_Message_Queues_MQ_Server.am
+
+if !BUILD_ACE_FOR_TAO
+noinst_PROGRAMS += mqserver
+
+mqserver_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+mqserver_SOURCES = \
+ MQ_Server.cpp \
+ test.h
+
+mqserver_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+endif !BUILD_ACE_FOR_TAO
+
+## Makefile.SV_Message_Queues_TMQ_Client.am
+
+if !BUILD_ACE_FOR_TAO
+noinst_PROGRAMS += tmqclient
+
+tmqclient_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+tmqclient_SOURCES = \
+ TMQ_Client.cpp \
+ test.h
+
+tmqclient_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+endif !BUILD_ACE_FOR_TAO
+
+## Makefile.SV_Message_Queues_TMQ_Server.am
+
+if !BUILD_ACE_FOR_TAO
+noinst_PROGRAMS += tmqserver
+
+tmqserver_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+tmqserver_SOURCES = \
+ TMQ_Server.cpp \
+ test.h
+
+tmqserver_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+endif !BUILD_ACE_FOR_TAO
+
+## Clean up template repositories, etc.
+clean-local:
+ -rm -f *~ *.bak *.rpo *.sym lib*.*_pure_* core core.*
+ -rm -f gcctemp.c gcctemp so_locations *.ics
+ -rm -rf cxx_repository ptrepository ti_files
+ -rm -rf templateregistry ir.out
+ -rm -rf ptrepository SunWS_cache Templates.DB
diff --git a/ACE/examples/System_V_IPC/SV_Message_Queues/SV_Message_Queues.mpc b/ACE/examples/System_V_IPC/SV_Message_Queues/SV_Message_Queues.mpc
new file mode 100644
index 00000000000..62cb7a0a819
--- /dev/null
+++ b/ACE/examples/System_V_IPC/SV_Message_Queues/SV_Message_Queues.mpc
@@ -0,0 +1,32 @@
+// -*- MPC -*-
+// $Id$
+
+project(*MQ Client) : aceexe {
+ avoids += ace_for_tao
+ exename = mqclient
+ Source_Files {
+ MQ_Client.cpp
+ }
+}
+project(*MQ Server) : aceexe {
+ avoids += ace_for_tao
+ exename = mqserver
+ Source_Files {
+ MQ_Server.cpp
+ }
+}
+project(*TMQ Client) : aceexe {
+ avoids += ace_for_tao
+ exename = tmqclient
+ Source_Files {
+ TMQ_Client.cpp
+ }
+}
+project(*TMQ Server) : aceexe {
+ avoids += ace_for_tao
+ exename = tmqserver
+ Source_Files {
+ TMQ_Server.cpp
+ }
+}
+
diff --git a/ACE/examples/System_V_IPC/SV_Message_Queues/TMQ_Client.cpp b/ACE/examples/System_V_IPC/SV_Message_Queues/TMQ_Client.cpp
new file mode 100644
index 00000000000..d48939845d5
--- /dev/null
+++ b/ACE/examples/System_V_IPC/SV_Message_Queues/TMQ_Client.cpp
@@ -0,0 +1,52 @@
+// $Id$
+
+#include "ace/Typed_SV_Message_Queue.h"
+
+// FUZZ: disable check_for_streams_include
+#include "ace/streams.h"
+
+#include "ace/Log_Msg.h"
+#include "test.h"
+#include "ace/OS_NS_stdio.h"
+#include "ace/OS_NS_unistd.h"
+
+ACE_RCSID(SV_Message_Queues, TMQ_Client, "$Id$")
+
+int
+ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ long pid = long (ACE_OS::getpid ());
+
+ ACE_Typed_SV_Message_Queue<Message_Data> msgque (key_t (SRV_KEY));
+
+ Message_Data msg_data (pid,
+ ACE_OS::cuserid (static_cast<char *> (0)),
+ "did you get this?");
+
+ ACE_Typed_SV_Message<Message_Data> send_msg (msg_data,
+ SRV_ID,
+ msg_data.length ()),
+ recv_msg (pid);
+
+ if (msgque.send (send_msg) < 0)
+ ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("%p\n"),
+ ACE_TEXT ("msgque.send")), 1);
+
+ if (msgque.recv (recv_msg) < 0)
+ ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("%p\n"),
+ ACE_TEXT ("msgque.recv")), 1);
+
+ Message_Data &recv_msg_data = recv_msg.data ();
+
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("a message of length %d")
+ ACE_TEXT (" received from server %d")
+ ACE_TEXT (" (user %C): %C\n"),
+ recv_msg_data.length (),
+ recv_msg_data.pid (),
+ recv_msg_data.user (),
+ recv_msg_data.text ()));
+
+ return 0;
+}
+
diff --git a/ACE/examples/System_V_IPC/SV_Message_Queues/TMQ_Server.cpp b/ACE/examples/System_V_IPC/SV_Message_Queues/TMQ_Server.cpp
new file mode 100644
index 00000000000..0da9aeec763
--- /dev/null
+++ b/ACE/examples/System_V_IPC/SV_Message_Queues/TMQ_Server.cpp
@@ -0,0 +1,78 @@
+// $Id$
+
+#include "ace/Signal.h"
+#include "ace/Typed_SV_Message_Queue.h"
+
+#include "test.h"
+
+// FUZZ: disable check_for_streams_include
+#include "ace/streams.h"
+
+#include "ace/Log_Msg.h"
+#include "ace/OS_NS_stdio.h"
+#include "ace/OS_NS_stdlib.h"
+#include "ace/OS_NS_unistd.h"
+
+ACE_RCSID(SV_Message_Queues, TMQ_Server, "$Id$")
+
+#if defined (ACE_HAS_SYSV_IPC) && !defined(ACE_LACKS_SYSV_SHMEM)
+
+// Must be global for signal Message...
+static ACE_Typed_SV_Message_Queue<Message_Data> ace_sv_message_queue
+ (SRV_KEY, ACE_Typed_SV_Message_Queue<Message_Data>::ACE_CREATE);
+
+extern "C" void
+handler (int)
+{
+ if (ace_sv_message_queue.remove () < 0)
+ ACE_ERROR ((LM_ERROR, "%p\n%a", "ace_sv_message_queue.recv", 1));
+ ACE_OS::exit (0);
+}
+
+int
+main (int, char *[])
+{
+ char *username = ACE_OS::cuserid (static_cast<char *> (0));
+ Message_Data msg_data ((int) ACE_OS::getpid (), username, "I received your message.");
+ ACE_Typed_SV_Message<Message_Data> send_msg (msg_data, 0, msg_data.length ());
+ ACE_Typed_SV_Message<Message_Data> recv_msg (SRV_ID);
+
+ // Register a signal handler.
+ ACE_Sig_Action sa ((ACE_SignalHandler) handler, SIGINT);
+ ACE_UNUSED_ARG (sa);
+
+ for (;;)
+ {
+ if (ace_sv_message_queue.recv (recv_msg) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "ace_sv_message_queue.recv"), 1);
+
+ Message_Data &recv_msg_data = recv_msg.data ();
+
+ cout << "a msg of length "
+ << recv_msg_data.length ()
+ << " sent from client "
+ << recv_msg_data.pid ()
+ << " (user "
+ << recv_msg_data.user () << "): "
+ << recv_msg_data.text () << "\n";
+ cout.flush ();
+
+ send_msg.type (recv_msg_data.pid ());
+
+ if (ace_sv_message_queue.send (send_msg) < 0)
+ ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "ace_sv_message_queue.send"), 1);
+ }
+
+ ACE_NOTREACHED (return 0;)
+}
+
+#else
+
+int ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ ACE_ERROR ((LM_ERROR,
+ "SYSV IPC, or SYSV SHMEM is not supported on this platform\n"));
+ return 0;
+}
+#endif /* ACE_HAS_SYSV_IPC && !ACE_LACKS_SYSV_SHMEM */
+
diff --git a/ACE/examples/System_V_IPC/SV_Message_Queues/test.h b/ACE/examples/System_V_IPC/SV_Message_Queues/test.h
new file mode 100644
index 00000000000..f17cf11c63e
--- /dev/null
+++ b/ACE/examples/System_V_IPC/SV_Message_Queues/test.h
@@ -0,0 +1,58 @@
+/* -*- C++ -*- */
+// $Id$
+
+#include "ace/OS_NS_string.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/SV_Message.h"
+
+#define MSGSZ 128
+#define SRV_KEY ACE_DEFAULT_SHM_KEY
+#define SRV_ID 1
+
+class Message_Data
+{
+public:
+ Message_Data (long p = -1,
+ const char user[] = "",
+ const char text[] = ""): pid_ (p)
+ {
+ ACE_OS::strncpy (this->username_, user, 9);
+ ACE_OS::strncpy (this->mtext_, text, MSGSZ);
+ }
+
+ long pid (void) { return this->pid_; }
+ void pid (long p) { this->pid_ = p; }
+ char *user (void) { return this->username_; }
+ void user (char user[]) { ACE_OS::strncpy (this->username_, user, 9); }
+ char *text (void) { return this->mtext_; }
+ void text (char text[]) { ACE_OS::strncpy (this->mtext_, text, MSGSZ); }
+ int length (void) { return sizeof *this - sizeof this->mtext_ + ACE_OS::strlen (this->mtext_) + 1; }
+
+protected:
+ long pid_;
+ char username_[9];
+ char mtext_[MSGSZ];
+};
+
+class Message_Block : public ACE_SV_Message, public Message_Data
+{
+ // = TITLE
+ // Stores message content.
+ // = DESCRIPTION
+ // This may not be 100 percent portable on all C++ compilers since
+ // it relies on inheritance to be "concatenation."
+ //
+public:
+ Message_Block (long t,
+ long p = 0,
+ const char login[] = "",
+ const char message[] = "")
+ : ACE_SV_Message (t),
+ Message_Data (p, login, message)
+ {}
+};
+
diff --git a/ACE/examples/System_V_IPC/SV_Semaphores/.cvsignore b/ACE/examples/System_V_IPC/SV_Semaphores/.cvsignore
new file mode 100644
index 00000000000..bb37ee6c9a7
--- /dev/null
+++ b/ACE/examples/System_V_IPC/SV_Semaphores/.cvsignore
@@ -0,0 +1,2 @@
+sem1
+sem2
diff --git a/ACE/examples/System_V_IPC/SV_Semaphores/Makefile.am b/ACE/examples/System_V_IPC/SV_Semaphores/Makefile.am
new file mode 100644
index 00000000000..de9a88952a6
--- /dev/null
+++ b/ACE/examples/System_V_IPC/SV_Semaphores/Makefile.am
@@ -0,0 +1,56 @@
+## Process this file with automake to create Makefile.in
+##
+## $Id$
+##
+## This file was generated by MPC. Any changes made directly to
+## this file will be lost the next time it is generated.
+##
+## MPC Command:
+## /acebuilds/ACE_wrappers-repository/bin/mwc.pl -include /acebuilds/MPC/config -include /acebuilds/MPC/templates -feature_file /acebuilds/ACE_wrappers-repository/local.features -noreldefs -type automake -exclude build,Kokyu
+
+ACE_BUILDDIR = $(top_builddir)
+ACE_ROOT = $(top_srcdir)
+
+noinst_PROGRAMS =
+
+## Makefile.SV_Semaphores_1.am
+
+if !BUILD_ACE_FOR_TAO
+noinst_PROGRAMS += sem1
+
+sem1_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+sem1_SOURCES = \
+ Semaphores_1.cpp
+
+sem1_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+endif !BUILD_ACE_FOR_TAO
+
+## Makefile.SV_Semaphores_2.am
+
+if !BUILD_ACE_FOR_TAO
+noinst_PROGRAMS += sem2
+
+sem2_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+sem2_SOURCES = \
+ Semaphores_2.cpp
+
+sem2_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+endif !BUILD_ACE_FOR_TAO
+
+## Clean up template repositories, etc.
+clean-local:
+ -rm -f *~ *.bak *.rpo *.sym lib*.*_pure_* core core.*
+ -rm -f gcctemp.c gcctemp so_locations *.ics
+ -rm -rf cxx_repository ptrepository ti_files
+ -rm -rf templateregistry ir.out
+ -rm -rf ptrepository SunWS_cache Templates.DB
diff --git a/ACE/examples/System_V_IPC/SV_Semaphores/SV_Semaphores.mpc b/ACE/examples/System_V_IPC/SV_Semaphores/SV_Semaphores.mpc
new file mode 100644
index 00000000000..647e4a4cf5a
--- /dev/null
+++ b/ACE/examples/System_V_IPC/SV_Semaphores/SV_Semaphores.mpc
@@ -0,0 +1,17 @@
+// -*- MPC -*-
+// $Id$
+
+project(*1) : aceexe {
+ avoids += ace_for_tao
+ exename = sem1
+ Source_Files {
+ Semaphores_1.cpp
+ }
+}
+project(*2) : aceexe {
+ avoids += ace_for_tao
+ exename = sem2
+ Source_Files {
+ Semaphores_2.cpp
+ }
+}
diff --git a/ACE/examples/System_V_IPC/SV_Semaphores/Semaphores_1.cpp b/ACE/examples/System_V_IPC/SV_Semaphores/Semaphores_1.cpp
new file mode 100644
index 00000000000..2331ea772ec
--- /dev/null
+++ b/ACE/examples/System_V_IPC/SV_Semaphores/Semaphores_1.cpp
@@ -0,0 +1,94 @@
+// $Id$
+
+#include "ace/SV_Shared_Memory.h"
+#include "ace/SV_Semaphore_Simple.h"
+#include "ace/SV_Semaphore_Complex.h"
+#include "ace/Shared_Memory_Pool.h"
+#include "ace/Malloc_T.h"
+#include "ace/OS_NS_unistd.h"
+
+
+ACE_RCSID (SV_Semaphores,
+ Semaphores_1,
+ "$Id$")
+
+
+#if defined (ACE_HAS_SYSV_IPC) && !defined(ACE_LACKS_SYSV_SHMEM)
+
+// Shared memory allocator (note that this chews up the
+// ACE_DEFAULT_SEM_KEY).
+static ACE_Malloc<ACE_SHARED_MEMORY_POOL, ACE_SV_Semaphore_Simple> alloc;
+
+const int SEM_KEY = ACE_DEFAULT_SEM_KEY + 1;
+
+static int
+parent (char *shm)
+{
+ char *s = shm;
+
+ ACE_SV_Semaphore_Complex sem (SEM_KEY, ACE_SV_Semaphore_Complex::ACE_CREATE, 0, 2);
+
+ for (char c = 'a'; c <= 'z'; c++)
+ *s++ = c;
+
+ *s = '\0';
+
+ if (sem.release (0) == -1)
+ ACE_ERROR ((LM_ERROR, "%p", "parent sem.release(0)"));
+ else if (sem.acquire (1) == -1)
+ ACE_ERROR ((LM_ERROR, "%p", "parent sem.acquire(1)"));
+
+ if (alloc.remove () == -1)
+ ACE_ERROR ((LM_ERROR, "%p\n", "alloc.remove"));
+ if (sem.remove () == -1)
+ ACE_ERROR ((LM_ERROR, "%p\n", "sem.remove"));
+ return 0;
+}
+
+static int
+child (char *shm)
+{
+ ACE_SV_Semaphore_Complex sem (SEM_KEY, ACE_SV_Semaphore_Complex::ACE_CREATE, 0, 2);
+
+ while (sem.tryacquire (0) == -1)
+ if (errno == EAGAIN)
+ ACE_DEBUG ((LM_DEBUG, "spinning in client!\n"));
+ else
+ ACE_ERROR_RETURN ((LM_ERROR, "client mutex.tryacquire(0)"), 1);
+
+ for (char *s = (char *) shm; *s != '\0'; s++)
+ ACE_DEBUG ((LM_DEBUG, "%c", *s));
+
+ ACE_DEBUG ((LM_DEBUG, "\n"));
+
+ if (sem.release (1) < 0)
+ ACE_ERROR ((LM_ERROR, "client sem.release(1)"));
+ return 0;
+}
+
+int
+main (int, char *[])
+{
+ char *shm = (char *) alloc.malloc (27);
+
+ switch (ACE_OS::fork ())
+ {
+ case -1:
+ ACE_ERROR_RETURN ((LM_ERROR, "fork failed\n"), -1);
+ /* NOTREACHED */
+ case 0:
+ // Child.
+ return child (shm);
+ default:
+ return parent (shm);
+ }
+}
+#else
+int ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ ACE_ERROR ((LM_ERROR,
+ "SYSV IPC, or SYSV SHMEM is not supported on this platform\n"));
+ return 0;
+}
+#endif /* ACE_HAS_SYSV_IPC */
+
diff --git a/ACE/examples/System_V_IPC/SV_Semaphores/Semaphores_2.cpp b/ACE/examples/System_V_IPC/SV_Semaphores/Semaphores_2.cpp
new file mode 100644
index 00000000000..e0ae9cd2bb5
--- /dev/null
+++ b/ACE/examples/System_V_IPC/SV_Semaphores/Semaphores_2.cpp
@@ -0,0 +1,110 @@
+// $Id$
+
+// Illustrates the use of the ACE_SV_Semaphore_Complex class and the
+// ACE_Malloc class using the ACE_Shared_Memory_Pool (which uses
+// System V shared memory). Note that it doesn't matter whether the
+// parent or the child creates the semaphore since Semaphore_Complex
+// will correctly serialize the intialization of the mutex and synch
+// objects.
+
+#include "ace/Malloc_T.h"
+#include "ace/Shared_Memory_Pool.h"
+#include "ace/SV_Semaphore_Complex.h"
+#include "ace/OS_NS_unistd.h"
+
+ACE_RCSID(SV_Semaphores, Semaphores_2, "$Id$")
+
+#if defined (ACE_HAS_SYSV_IPC) && !defined(ACE_LACKS_SYSV_SHMEM)
+
+// Shared memory allocator (note that this chews up the
+// ACE_DEFAULT_SEM_KEY).
+static ACE_Malloc<ACE_SHARED_MEMORY_POOL, ACE_SV_Semaphore_Simple> my_alloc;
+
+const int SEM_KEY_1 = ACE_DEFAULT_SEM_KEY + 1;
+const int SEM_KEY_2 = ACE_DEFAULT_SEM_KEY + 2;
+
+static int
+parent (char *shm)
+{
+ char *s = shm;
+
+ // Both semaphores are initially created with a count of 0, i.e.,
+ // they are "locked."
+ ACE_SV_Semaphore_Complex mutex (SEM_KEY_1, ACE_SV_Semaphore_Complex::ACE_CREATE, 0);
+ ACE_SV_Semaphore_Complex synch (SEM_KEY_2, ACE_SV_Semaphore_Complex::ACE_CREATE, 0);
+
+ // This is a critical section, which is protected by the mutex
+ // semaphore.
+ for (char c = 'a'; c <= 'z'; c++)
+ *s++ = c;
+
+ *s = '\0';
+
+ if (mutex.release () == -1)
+ ACE_ERROR ((LM_ERROR, "%p", "parent mutex.release"));
+ else if (synch.acquire () == -1)
+ ACE_ERROR ((LM_ERROR, "%p", "parent synch.acquire"));
+
+ if (my_alloc.remove () == -1)
+ ACE_ERROR ((LM_ERROR, "%p\n", "my_alloc.remove"));
+ if (mutex.remove () == -1)
+ ACE_ERROR ((LM_ERROR, "%p\n", "mutex.remove"));
+ if (synch.remove () == -1)
+ ACE_ERROR ((LM_ERROR, "%p\n", "synch.remove"));
+ return 0;
+}
+
+static int
+child (char *shm)
+{
+ // Both semaphores are initially created with a count of 0, i.e.,
+ // they are "locked."
+ ACE_SV_Semaphore_Complex mutex (SEM_KEY_1, ACE_SV_Semaphore_Complex::ACE_CREATE, 0);
+ ACE_SV_Semaphore_Complex synch (SEM_KEY_2, ACE_SV_Semaphore_Complex::ACE_CREATE, 0);
+
+ // Perform "busy waiting" here until we acquire the semaphore. This
+ // isn't really a good design -- it's just to illustrate that you
+ // can do non-blocking acquire() calls with the ACE System V
+ // semaphore wrappers.
+ while (mutex.tryacquire () == -1)
+ if (errno == EAGAIN)
+ ACE_DEBUG ((LM_DEBUG, "spinning in child!\n"));
+ else
+ ACE_ERROR_RETURN ((LM_ERROR, "child mutex.tryacquire"), 1);
+
+ for (char *s = (char *) shm; *s != '\0'; s++)
+ ACE_DEBUG ((LM_DEBUG, "%c", *s));
+
+ ACE_DEBUG ((LM_DEBUG, "\n"));
+
+ if (synch.release () == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, "child synch.release"), 1);
+ return 0;
+}
+
+int
+main (int, char *[])
+{
+ char *shm = (char *) my_alloc.malloc (27);
+
+ switch (ACE_OS::fork ())
+ {
+ case -1:
+ ACE_ERROR_RETURN ((LM_ERROR, "fork failed\n"), -1);
+ /* NOTREACHED */
+ case 0:
+ // Child.
+ return child (shm);
+ default:
+ return parent (shm);
+ }
+}
+#else
+int ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ ACE_ERROR ((LM_ERROR,
+ "SYSV IPC, or SYSV SHMEM is not supported on this platform\n"));
+ return 0;
+}
+#endif /* ACE_HAS_SYSV_IPC */
+
diff --git a/ACE/examples/System_V_IPC/SV_Shared_Memory/SV_Shared_Memory_Test.cpp b/ACE/examples/System_V_IPC/SV_Shared_Memory/SV_Shared_Memory_Test.cpp
new file mode 100644
index 00000000000..3a36e395d35
--- /dev/null
+++ b/ACE/examples/System_V_IPC/SV_Shared_Memory/SV_Shared_Memory_Test.cpp
@@ -0,0 +1,78 @@
+// $Id$
+
+#include "ace/SV_Shared_Memory.h"
+#include "ace/Log_Msg.h"
+#include "SV_Shared_Memory_Test.h"
+#include "ace/OS_NS_stdio.h"
+#include "ace/OS_NS_stdlib.h"
+#include "ace/OS_NS_unistd.h"
+
+ACE_RCSID(SV_Shared_Memory, SV_Shared_Memory_Test, "$Id$")
+
+#if defined (ACE_HAS_SYSV_IPC) && !defined(ACE_LACKS_SYSV_SHMEM)
+
+static void
+client (void)
+{
+ ACE_SV_Shared_Memory shm_client;
+
+ if (shm_client.open_and_attach (SHM_KEY, SHMSZ) == -1)
+ ACE_OS::perror ("open"), ACE_OS::exit (1);
+
+ for (char *s = (char *) shm_client.get_segment_ptr (); *s != '\0'; s++)
+ putchar (*s);
+
+ putchar ('\n');
+ *(char *) shm_client.get_segment_ptr () = '*';
+ ACE_OS::exit (0);
+}
+
+static void
+server (void)
+{
+ ACE_SV_Shared_Memory shm_server;
+
+ if (shm_server.open_and_attach (SHM_KEY, SHMSZ, ACE_SV_Shared_Memory::ACE_CREATE) == -1)
+ ACE_OS::perror ("open"), ACE_OS::exit (1);
+
+ char *s = (char *) shm_server.get_segment_ptr ();
+
+ for (char c = 'a'; c <= 'z'; c++)
+ *s++ = c;
+
+ *s = '\0';
+
+ for (s = (char *) shm_server.get_segment_ptr (); *s != '*'; )
+ ACE_OS::sleep (1);
+
+ if (shm_server.remove () < 0)
+ ACE_OS::perror ("remove"), ACE_OS::exit (1);
+ ACE_OS::exit (0);
+}
+
+int
+main (int, char *argv[])
+{
+ switch (ACE_OS::fork ())
+ {
+ case -1:
+ ACE_OS::perror (argv[0]), ACE_OS::exit (1);
+ case 0:
+ ACE_OS::sleep (1);
+ client ();
+ default:
+ server ();
+ }
+ return 0;
+}
+
+#else
+
+int ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ ACE_ERROR ((LM_ERROR,
+ "SYSV IPC, or SYSV SHMEM is not supported on this platform\n"));
+ return 0;
+}
+#endif /* ACE_HAS_SYSV_IPC && !ACE_LACKS_SYSV_SHMEM */
+
diff --git a/ACE/examples/System_V_IPC/SV_Shared_Memory/SV_Shared_Memory_Test.h b/ACE/examples/System_V_IPC/SV_Shared_Memory/SV_Shared_Memory_Test.h
new file mode 100644
index 00000000000..3cfff4672b9
--- /dev/null
+++ b/ACE/examples/System_V_IPC/SV_Shared_Memory/SV_Shared_Memory_Test.h
@@ -0,0 +1,12 @@
+/* -*- C++ -*- */
+// $Id$
+
+#include "ace/config-all.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#define SHMSZ 27
+#define SEM_KEY 1234
+#define SHM_KEY 5678
diff --git a/ACE/examples/TMCast/Makefile.am b/ACE/examples/TMCast/Makefile.am
new file mode 100644
index 00000000000..ad8cc650602
--- /dev/null
+++ b/ACE/examples/TMCast/Makefile.am
@@ -0,0 +1,13 @@
+## Process this file with automake to create Makefile.in
+##
+## $Id$
+##
+## This file was generated by MPC. Any changes made directly to
+## this file will be lost the next time it is generated.
+##
+## MPC Command:
+## /acebuilds/ACE_wrappers-repository/bin/mwc.pl -include /acebuilds/MPC/config -include /acebuilds/MPC/templates -feature_file /acebuilds/ACE_wrappers-repository/local.features -noreldefs -type automake -exclude build,Kokyu
+
+SUBDIRS = \
+ Member
+
diff --git a/ACE/examples/TMCast/Member/.cvsignore b/ACE/examples/TMCast/Member/.cvsignore
new file mode 100644
index 00000000000..fa6ecc72251
--- /dev/null
+++ b/ACE/examples/TMCast/Member/.cvsignore
@@ -0,0 +1 @@
+member
diff --git a/ACE/examples/TMCast/Member/Makefile.am b/ACE/examples/TMCast/Member/Makefile.am
new file mode 100644
index 00000000000..fe970a85ef5
--- /dev/null
+++ b/ACE/examples/TMCast/Member/Makefile.am
@@ -0,0 +1,45 @@
+## Process this file with automake to create Makefile.in
+##
+## $Id$
+##
+## This file was generated by MPC. Any changes made directly to
+## this file will be lost the next time it is generated.
+##
+## MPC Command:
+## /acebuilds/ACE_wrappers-repository/bin/mwc.pl -include /acebuilds/MPC/config -include /acebuilds/MPC/templates -feature_file /acebuilds/ACE_wrappers-repository/local.features -noreldefs -type automake -exclude build,Kokyu
+
+ACE_BUILDDIR = $(top_builddir)
+ACE_ROOT = $(top_srcdir)
+
+
+## Makefile.Member.am
+
+if BUILD_EXCEPTIONS
+if BUILD_THREADS
+if !BUILD_ACE_FOR_TAO
+
+noinst_PROGRAMS = member
+
+member_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR) \
+ -I$(ACE_ROOT)/protocols
+
+member_SOURCES = \
+ member.cpp
+
+member_LDADD = \
+ $(ACE_BUILDDIR)/protocols/ace/TMCast/libACE_TMCast.la \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+endif !BUILD_ACE_FOR_TAO
+endif BUILD_THREADS
+endif BUILD_EXCEPTIONS
+
+## Clean up template repositories, etc.
+clean-local:
+ -rm -f *~ *.bak *.rpo *.sym lib*.*_pure_* core core.*
+ -rm -f gcctemp.c gcctemp so_locations *.ics
+ -rm -rf cxx_repository ptrepository ti_files
+ -rm -rf templateregistry ir.out
+ -rm -rf ptrepository SunWS_cache Templates.DB
diff --git a/ACE/examples/TMCast/Member/Member.mpc b/ACE/examples/TMCast/Member/Member.mpc
new file mode 100644
index 00000000000..29f274f51f3
--- /dev/null
+++ b/ACE/examples/TMCast/Member/Member.mpc
@@ -0,0 +1,7 @@
+// -*- MPC -*-
+// $Id$
+
+project: aceexe, tmcast {
+ exename = member
+}
+
diff --git a/ACE/examples/TMCast/Member/README b/ACE/examples/TMCast/Member/README
new file mode 100644
index 00000000000..6a62a107a77
--- /dev/null
+++ b/ACE/examples/TMCast/Member/README
@@ -0,0 +1,36 @@
+Member example shows how you can build a simple multicast group
+using transactional multicast (TMCast). Each member can be either
+a sender or a receiver.
+
+The sender sends small messages to the multicast group with a random
+wait period in [0, 1] second range. The receiver is simply receiving
+those messages and prints them out.
+
+To start the sender you can execute something like this:
+
+$ ./member s sender-1 239.255.0.1:10000
+
+Here the first argument ('s') indicates that new member will be
+a sender. The second argument ('sender-1') is an id of the new
+member (each member of the group should have a unique id). And
+the third argument ('239.255.0.1:10000') specifies IPv4 multicast
+address and port (you can choose you own).
+
+To start the receiver you can execute similar command:
+
+$ ./member r receiver-1 239.255.0.1:10000
+
+After you have started both the receiver and the sender you
+should see a sequence of messages printed by the receiver.
+
+Note, since the group can exist with only one member for a
+very short period of time you should start first two members
+virtually at the same time. See TMCast documentation for more
+information about why it behaves this way.
+
+You may want to add more than one sender to the group if you
+want to see how TMCast operates in a totally-ordered mode.
+
+
+--
+Boris Kolpackov <boris@dre.vanderbilt.edu>
diff --git a/ACE/examples/TMCast/Member/member.cpp b/ACE/examples/TMCast/Member/member.cpp
new file mode 100644
index 00000000000..f89c68564ea
--- /dev/null
+++ b/ACE/examples/TMCast/Member/member.cpp
@@ -0,0 +1,93 @@
+// file : TMCast/Member/member.cpp
+// author : Boris Kolpackov <boris@dre.vanderbilt.edu>
+// cvs-id : $Id$
+
+#include "ace/Log_Msg.h"
+#include "ace/Time_Value.h"
+#include "ace/OS_NS_stdlib.h"
+#include "ace/OS_NS_unistd.h"
+#include "ace/OS_NS_stdio.h"
+#include "ace/OS_NS_time.h"
+#include "ace/OS_NS_string.h"
+
+#include "ace/TMCast/Group.hpp"
+
+class Args {};
+
+int
+ACE_TMAIN (int argc, ACE_TCHAR* argv[])
+{
+ int status = 0;
+ try
+ {
+ if (argc < 4) throw Args ();
+
+ bool receiver (true);
+
+ if (argv[1][0] == 'r') receiver = true;
+ else if (argv[1][0] == 's') receiver = false;
+ else throw Args ();
+
+ if (!receiver) ACE_OS::srand (ACE_OS::time ());
+
+ ACE_INET_Addr address (argv[3]);
+
+ ACE_TMCast::Group group (address, ACE_TEXT_ALWAYS_CHAR (argv[2]));
+
+ if (receiver)
+ {
+ for (char buffer[256];;)
+ {
+ group.recv (buffer, sizeof (buffer));
+
+ ACE_DEBUG ((LM_DEBUG, "%s\n", buffer));
+ }
+ }
+ else
+ {
+ char buffer[256];
+
+ for (unsigned long i = 0; i < 1000; i++)
+ {
+ // Sleep some random time around 1 sec.
+
+ ACE_UINT64 tmpl = 1000000U;
+ unsigned long t =
+ static_cast<unsigned long> (((tmpl * ACE_OS::rand ()) / RAND_MAX));
+
+ // ACE_DEBUG ((LM_DEBUG, "sleeping for %u\n", t));
+
+ ACE_OS::sleep (ACE_Time_Value (0, t));
+
+ ACE_OS::sprintf (buffer, "message # %lu", i);
+
+ try
+ {
+ group.send (buffer, ACE_OS::strlen (buffer) + 1);
+ }
+ catch (ACE_TMCast::Group::Aborted const&)
+ {
+ ACE_ERROR ((LM_ERROR, "%s has been aborted\n", buffer));
+ }
+ }
+ }
+ }
+ catch (Args const&)
+ {
+ ACE_ERROR ((LM_ERROR,
+ "Usage: member {r|s} <id> <IPv4 mcast address>:<port>\n"));
+ status++;
+ }
+ catch (ACE_TMCast::Group::Failed const&)
+ {
+ ACE_ERROR ((LM_ERROR,
+ "Group failure. Perhaps I am alone in the group.\n"));
+ status++;
+ }
+ catch (ACE_TMCast::Group::InsufficienSpace const&)
+ {
+ ACE_ERROR ((LM_ERROR, "Insufficient space in receive buffer.\n"));
+ status++;
+ }
+ return status;
+}
diff --git a/ACE/examples/Threads/.cvsignore b/ACE/examples/Threads/.cvsignore
new file mode 100644
index 00000000000..29680be7dcc
--- /dev/null
+++ b/ACE/examples/Threads/.cvsignore
@@ -0,0 +1,22 @@
+auto_event
+barrier1
+barrier2
+cancel
+future1
+future2
+manual_event
+process_mutex
+process_semaphore
+reader_writer
+recursive_mutex
+task_five
+task_four
+task_one
+task_three
+task_two
+thread_manager
+thread_pool
+thread_specific
+token
+tss1
+tss2
diff --git a/ACE/examples/Threads/Makefile.am b/ACE/examples/Threads/Makefile.am
new file mode 100644
index 00000000000..edd80b72542
--- /dev/null
+++ b/ACE/examples/Threads/Makefile.am
@@ -0,0 +1,408 @@
+## Process this file with automake to create Makefile.in
+##
+## $Id$
+##
+## This file was generated by MPC. Any changes made directly to
+## this file will be lost the next time it is generated.
+##
+## MPC Command:
+## /acebuilds/ACE_wrappers-repository/bin/mwc.pl -include /acebuilds/MPC/config -include /acebuilds/MPC/templates -feature_file /acebuilds/ACE_wrappers-repository/local.features -noreldefs -type automake -exclude build,Kokyu
+
+ACE_BUILDDIR = $(top_builddir)
+ACE_ROOT = $(top_srcdir)
+
+
+## Makefile.Threads_Auto_Event.am
+noinst_PROGRAMS = auto_event
+
+auto_event_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+auto_event_SOURCES = \
+ auto_event.cpp \
+ TSS_Data.h \
+ TSS_Obj.h \
+ TSS_Task.h \
+ thread_specific.h
+
+auto_event_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Makefile.Threads_Barrier1.am
+noinst_PROGRAMS += barrier1
+
+barrier1_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+barrier1_SOURCES = \
+ barrier1.cpp \
+ TSS_Data.h \
+ TSS_Obj.h \
+ TSS_Task.h \
+ thread_specific.h
+
+barrier1_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Makefile.Threads_Barrier2.am
+noinst_PROGRAMS += barrier2
+
+barrier2_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+barrier2_SOURCES = \
+ barrier2.cpp \
+ TSS_Data.h \
+ TSS_Obj.h \
+ TSS_Task.h \
+ thread_specific.h
+
+barrier2_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Makefile.Threads_Cancel.am
+noinst_PROGRAMS += cancel
+
+cancel_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+cancel_SOURCES = \
+ cancel.cpp \
+ TSS_Data.h \
+ TSS_Obj.h \
+ TSS_Task.h \
+ thread_specific.h
+
+cancel_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Makefile.Threads_Future1.am
+
+if !BUILD_ACE_FOR_TAO
+noinst_PROGRAMS += future1
+
+future1_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+future1_SOURCES = \
+ future1.cpp \
+ TSS_Data.h \
+ TSS_Obj.h \
+ TSS_Task.h \
+ thread_specific.h
+
+future1_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+endif !BUILD_ACE_FOR_TAO
+
+## Makefile.Threads_Future2.am
+
+if !BUILD_ACE_FOR_TAO
+noinst_PROGRAMS += future2
+
+future2_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+future2_SOURCES = \
+ future2.cpp \
+ TSS_Data.h \
+ TSS_Obj.h \
+ TSS_Task.h \
+ thread_specific.h
+
+future2_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+endif !BUILD_ACE_FOR_TAO
+
+## Makefile.Threads_Manual_Event.am
+noinst_PROGRAMS += manual_event
+
+manual_event_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+manual_event_SOURCES = \
+ manual_event.cpp \
+ TSS_Data.h \
+ TSS_Obj.h \
+ TSS_Task.h \
+ thread_specific.h
+
+manual_event_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Makefile.Threads_Process_Mutex.am
+
+if !BUILD_ACE_FOR_TAO
+noinst_PROGRAMS += process_mutex
+
+process_mutex_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+process_mutex_SOURCES = \
+ process_mutex.cpp \
+ TSS_Data.h \
+ TSS_Obj.h \
+ TSS_Task.h \
+ thread_specific.h
+
+process_mutex_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+endif !BUILD_ACE_FOR_TAO
+
+## Makefile.Threads_Process_Semaphore.am
+
+if !BUILD_ACE_FOR_TAO
+noinst_PROGRAMS += process_semaphore
+
+process_semaphore_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+process_semaphore_SOURCES = \
+ process_semaphore.cpp \
+ TSS_Data.h \
+ TSS_Obj.h \
+ TSS_Task.h \
+ thread_specific.h
+
+process_semaphore_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+endif !BUILD_ACE_FOR_TAO
+
+## Makefile.Threads_Reader_Writer.am
+noinst_PROGRAMS += reader_writer
+
+reader_writer_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+reader_writer_SOURCES = \
+ reader_writer.cpp \
+ TSS_Data.h \
+ TSS_Obj.h \
+ TSS_Task.h \
+ thread_specific.h
+
+reader_writer_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Makefile.Threads_Recursive_Mutex.am
+noinst_PROGRAMS += recursive_mutex
+
+recursive_mutex_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+recursive_mutex_SOURCES = \
+ recursive_mutex.cpp \
+ TSS_Data.h \
+ TSS_Obj.h \
+ TSS_Task.h \
+ thread_specific.h
+
+recursive_mutex_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Makefile.Threads_Task_Five.am
+noinst_PROGRAMS += task_five
+
+task_five_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+task_five_SOURCES = \
+ task_five.cpp \
+ TSS_Data.h \
+ TSS_Obj.h \
+ TSS_Task.h \
+ thread_specific.h
+
+task_five_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Makefile.Threads_Task_Four.am
+noinst_PROGRAMS += task_four
+
+task_four_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+task_four_SOURCES = \
+ task_four.cpp \
+ TSS_Data.h \
+ TSS_Obj.h \
+ TSS_Task.h \
+ thread_specific.h
+
+task_four_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Makefile.Threads_Task_One.am
+noinst_PROGRAMS += task_one
+
+task_one_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+task_one_SOURCES = \
+ task_one.cpp \
+ TSS_Data.h \
+ TSS_Obj.h \
+ TSS_Task.h \
+ thread_specific.h
+
+task_one_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Makefile.Threads_Task_Three.am
+noinst_PROGRAMS += task_three
+
+task_three_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+task_three_SOURCES = \
+ task_three.cpp \
+ TSS_Data.h \
+ TSS_Obj.h \
+ TSS_Task.h \
+ thread_specific.h
+
+task_three_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Makefile.Threads_Task_Two.am
+noinst_PROGRAMS += task_two
+
+task_two_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+task_two_SOURCES = \
+ task_two.cpp \
+ TSS_Data.h \
+ TSS_Obj.h \
+ TSS_Task.h \
+ thread_specific.h
+
+task_two_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Makefile.Threads_Thread_Manager.am
+noinst_PROGRAMS += thread_manager
+
+thread_manager_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+thread_manager_SOURCES = \
+ thread_manager.cpp \
+ TSS_Data.h \
+ TSS_Obj.h \
+ TSS_Task.h \
+ thread_specific.h
+
+thread_manager_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Makefile.Threads_Thread_Pool.am
+noinst_PROGRAMS += thread_pool
+
+thread_pool_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+thread_pool_SOURCES = \
+ thread_pool.cpp \
+ TSS_Data.h \
+ TSS_Obj.h \
+ TSS_Task.h \
+ thread_specific.h
+
+thread_pool_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Makefile.Threads_Thread_Specific.am
+noinst_PROGRAMS += thread_specific
+
+thread_specific_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+thread_specific_SOURCES = \
+ thread_specific.cpp \
+ thread_specific.h
+
+thread_specific_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Makefile.Threads_Token.am
+noinst_PROGRAMS += token
+
+token_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+token_SOURCES = \
+ token.cpp \
+ TSS_Data.h \
+ TSS_Obj.h \
+ TSS_Task.h \
+ thread_specific.h
+
+token_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Makefile.Threads_Tss1.am
+noinst_PROGRAMS += tss1
+
+tss1_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+tss1_SOURCES = \
+ tss1.cpp \
+ TSS_Data.h \
+ TSS_Obj.h \
+ TSS_Task.h \
+ thread_specific.h
+
+tss1_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Makefile.Threads_Tss2.am
+noinst_PROGRAMS += tss2
+
+tss2_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+tss2_SOURCES = \
+ tss2.cpp \
+ TSS_Data.h \
+ TSS_Obj.h \
+ TSS_Task.h \
+ thread_specific.h
+
+tss2_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Clean up template repositories, etc.
+clean-local:
+ -rm -f *~ *.bak *.rpo *.sym lib*.*_pure_* core core.*
+ -rm -f gcctemp.c gcctemp so_locations *.ics
+ -rm -rf cxx_repository ptrepository ti_files
+ -rm -rf templateregistry ir.out
+ -rm -rf ptrepository SunWS_cache Templates.DB
diff --git a/ACE/examples/Threads/TSS_Data.h b/ACE/examples/Threads/TSS_Data.h
new file mode 100644
index 00000000000..3c9dfcfe28c
--- /dev/null
+++ b/ACE/examples/Threads/TSS_Data.h
@@ -0,0 +1,40 @@
+// $Id$
+
+// ============================================================================
+//
+// = LIBRARY
+// examples
+//
+// = FILENAME
+// TSS_Data.cpp
+//
+// = AUTHOR
+// Prashant Jain and Doug Schmidt
+//
+// ============================================================================
+
+#include "ace/Singleton.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/Synch_Traits.h"
+
+class TSS_Data
+ // = TITLE
+ // Data that is stored in thread-specific storage.
+{
+public:
+ void *data (void) { return this->data_; }
+ void data (void *v) { this->data_ = v; }
+
+private:
+ // = data_ will be thread-specific data so it doesn't need a lock.
+ void *data_;
+};
+
+typedef ACE_TSS_Singleton<TSS_Data, ACE_SYNCH_MUTEX> TSS_DATA;
+
+
+
diff --git a/ACE/examples/Threads/TSS_Obj.h b/ACE/examples/Threads/TSS_Obj.h
new file mode 100644
index 00000000000..7dc4e469851
--- /dev/null
+++ b/ACE/examples/Threads/TSS_Obj.h
@@ -0,0 +1,39 @@
+// $Id$
+
+// ============================================================================
+//
+// = LIBRARY
+// tests
+//
+// = FILENAME
+// TSS_Test.cpp
+//
+// = DESCRIPTION
+// This program tests various features of ACE_Thread and the
+// thread-specific storage variant of <ACE_SingletonEx>.
+//
+// = AUTHOR
+// Prashant Jain and Doug Schmidt
+//
+// ============================================================================
+
+#include "ace/Atomic_Op.h"
+#include "ace/Synch_Traits.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+class TSS_Obj
+ // = TITLE
+ // This object is stored in thread-specific storage.
+{
+public:
+ TSS_Obj (void);
+ ~TSS_Obj (void);
+
+private:
+
+ static ACE_Atomic_Op<ACE_SYNCH_MUTEX, int> count_;
+};
+
diff --git a/ACE/examples/Threads/TSS_Task.h b/ACE/examples/Threads/TSS_Task.h
new file mode 100644
index 00000000000..0612f0c46a9
--- /dev/null
+++ b/ACE/examples/Threads/TSS_Task.h
@@ -0,0 +1,43 @@
+/* -*- C++ -*- */
+
+// $Id$
+
+// ============================================================================
+//
+// = LIBRARY
+// tests
+//
+// = FILENAME
+// TSS_Task.h
+//
+// = AUTHOR
+// Prashant Jain and Doug Schmidt
+//
+// ============================================================================
+
+#include "ace/config-all.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/Token.h"
+#include "ace/Atomic_Op.h"
+
+class Test_Task
+{
+public:
+
+ Test_Task (void);
+ ~Test_Task (void);
+
+ int open (void *arg);
+
+ static void *svc (void *arg);
+
+ static ACE_Atomic_Op<ACE_Token, int> wait_count_;
+ static ACE_Atomic_Op<ACE_Token, int> max_count_;
+
+private:
+ static ACE_Atomic_Op<ACE_Token, int> count_;
+};
diff --git a/ACE/examples/Threads/Threads.mpc b/ACE/examples/Threads/Threads.mpc
new file mode 100644
index 00000000000..2c57feda243
--- /dev/null
+++ b/ACE/examples/Threads/Threads.mpc
@@ -0,0 +1,139 @@
+// -*- MPC -*-
+// $Id$
+
+project(*auto_event) : aceexe {
+ exename = auto_event
+ Source_Files {
+ auto_event.cpp
+ }
+}
+project(*barrier1) : aceexe {
+ exename = barrier1
+ Source_Files {
+ barrier1.cpp
+ }
+}
+project(*barrier2) : aceexe {
+ exename = barrier2
+ Source_Files {
+ barrier2.cpp
+ }
+}
+project(*cancel) : aceexe {
+ exename = cancel
+ Source_Files {
+ cancel.cpp
+ }
+}
+project(*future1) : aceexe {
+ avoids += ace_for_tao
+ exename = future1
+ Source_Files {
+ future1.cpp
+ }
+}
+project(*future2) : aceexe {
+ avoids += ace_for_tao
+ exename = future2
+ Source_Files {
+ future2.cpp
+ }
+}
+project(*manual_event) : aceexe {
+ exename = manual_event
+ Source_Files {
+ manual_event.cpp
+ }
+}
+project(*process_mutex) : aceexe {
+ avoids += ace_for_tao
+ exename = process_mutex
+ Source_Files {
+ process_mutex.cpp
+ }
+}
+project(*process_semaphore) : aceexe {
+ avoids += ace_for_tao
+ exename = process_semaphore
+ Source_Files {
+ process_semaphore.cpp
+ }
+}
+project(*reader_writer) : aceexe {
+ exename = reader_writer
+ Source_Files {
+ reader_writer.cpp
+ }
+}
+project(*recursive_mutex) : aceexe {
+ exename = recursive_mutex
+ Source_Files {
+ recursive_mutex.cpp
+ }
+}
+project(*task_five) : aceexe {
+ exename = task_five
+ Source_Files {
+ task_five.cpp
+ }
+}
+project(*task_four) : aceexe {
+ exename = task_four
+ Source_Files {
+ task_four.cpp
+ }
+}
+project(*task_three) : aceexe {
+ exename = task_three
+ Source_Files {
+ task_three.cpp
+ }
+}
+project(*task_two) : aceexe {
+ exename = task_two
+ Source_Files {
+ task_two.cpp
+ }
+}
+project(*task_one) : aceexe {
+ exename = task_one
+ Source_Files {
+ task_one.cpp
+ }
+}
+project(*thread_manager) : aceexe {
+ exename = thread_manager
+ Source_Files {
+ thread_manager.cpp
+ }
+}
+project(*thread_pool) : aceexe {
+ exename = thread_pool
+ Source_Files {
+ thread_pool.cpp
+ }
+}
+project(*thread_specific) : aceexe {
+ exename = thread_specific
+ Source_Files {
+ thread_specific.cpp
+ }
+}
+project(*token) : aceexe {
+ exename = token
+ Source_Files {
+ token.cpp
+ }
+}
+project(*tss1) : aceexe {
+ exename = tss1
+ Source_Files {
+ tss1.cpp
+ }
+}
+project(*tss2) : aceexe {
+ exename = tss2
+ Source_Files {
+ tss2.cpp
+ }
+}
diff --git a/ACE/examples/Threads/auto_event.cpp b/ACE/examples/Threads/auto_event.cpp
new file mode 100644
index 00000000000..e568ffe84d1
--- /dev/null
+++ b/ACE/examples/Threads/auto_event.cpp
@@ -0,0 +1,120 @@
+// $Id$
+
+// This test shows the use of an ACE_Auto_Event as a signaling
+// mechanism. Two threads are created (one a reader, the other a
+// writer). The reader waits till the writer has completed
+// calculations. Upon waking up the reader prints the data calculated
+// by the writer. The writer thread calculates the value and signals
+// the reader when the calculation completes.
+
+#include "ace/OS_NS_unistd.h"
+#include "ace/OS_main.h"
+#include "ace/Service_Config.h"
+#include "ace/Auto_Event.h"
+#include "ace/Singleton.h"
+#include "ace/Thread_Manager.h"
+
+ACE_RCSID(Threads, auto_event, "$Id$")
+
+#if defined (ACE_HAS_THREADS)
+// Shared event between reader and writer. The ACE_Thread_Mutex is
+// necessary to make sure that only one ACE_Auto_Event is created.
+// The default constructor for ACE_Auto_Event sets it initially into
+// the non-signaled state.
+
+typedef ACE_Singleton <ACE_Auto_Event, ACE_Thread_Mutex> EVENT;
+
+// work time for writer
+static int work_time;
+
+// Reader thread.
+static void *
+reader (void *arg)
+{
+ // Shared data via a reference.
+ int& data = *(int *) arg;
+
+ // Wait for writer to complete.
+
+ ACE_DEBUG ((LM_DEBUG, "(%t) reader: waiting...... \n"));
+
+ if (EVENT::instance ()->wait () == -1)
+ {
+ ACE_ERROR ((LM_ERROR, "thread wait failed"));
+ ACE_OS::exit (0);
+ }
+
+ // Read shared data.
+ ACE_DEBUG ((LM_DEBUG, "(%t) reader: value of data is: %d \n", data));
+
+ return 0;
+}
+
+// Writer thread.
+static void *
+writer (void *arg)
+{
+ int& data = *(int *) arg;
+
+ // Calculate (work).
+ ACE_DEBUG ((LM_DEBUG, "(%t) writer: working for %d secs\n", work_time));
+ ACE_OS::sleep (work_time);
+
+ // Write shared data.
+ data = 42;
+
+ // Wake up reader.
+ ACE_DEBUG ((LM_DEBUG, "(%t) writer: calculation complete, waking reader\n"));
+
+ if (EVENT::instance ()->signal () == -1)
+ {
+ ACE_ERROR ((LM_ERROR, "thread signal failed"));
+ ACE_OS::exit (0);
+ }
+
+ return 0;
+}
+
+int
+ACE_TMAIN (int argc, ACE_TCHAR **argv)
+{
+ // Shared data: set by writer, read by reader.
+ int data;
+
+ // Work time for writer.
+ work_time = argc == 2 ? ACE_OS::atoi (argv[1]) : 5;
+
+ // threads manager
+ ACE_Thread_Manager& tm = *ACE_Thread_Manager::instance ();
+
+ // Create reader thread.
+ if (tm.spawn ((ACE_THR_FUNC) reader, (void *) &data) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, "thread create for reader failed"), -1);
+
+ // Create writer thread.
+ if (tm.spawn ((ACE_THR_FUNC) writer, (void *) &data) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, "thread create for writer failed"), -1);
+
+ // Wait for both.
+ if (tm.wait () == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, "thread wait failed"), -1);
+ else
+ ACE_DEBUG ((LM_ERROR, "graceful exit\n"));
+
+ return 0;
+}
+
+#if defined (ACE_HAS_EXPLICIT_STATIC_TEMPLATE_MEMBER_INSTANTIATION)
+template ACE_Singleton<ACE_Auto_Event, ACE_Thread_Mutex> *
+ ACE_Singleton<ACE_Auto_Event, ACE_Thread_Mutex>::singleton_;
+#endif /* ACE_HAS_EXPLICIT_STATIC_TEMPLATE_MEMBER_INSTANTIATION */
+
+
+#else
+int
+ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ ACE_ERROR ((LM_ERROR, "threads not supported on this platform\n"));
+ return 0;
+}
+#endif /* ACE_HAS_THREADS */
diff --git a/ACE/examples/Threads/barrier1.cpp b/ACE/examples/Threads/barrier1.cpp
new file mode 100644
index 00000000000..4d3762b1eb6
--- /dev/null
+++ b/ACE/examples/Threads/barrier1.cpp
@@ -0,0 +1,83 @@
+// $Id$
+
+// This test program illustrates how the ACE barrier synchronization
+// mechanisms work.
+
+#include "ace/OS_main.h"
+#include "ace/Barrier.h"
+#include "ace/Thread_Manager.h"
+#include "ace/Service_Config.h"
+
+ACE_RCSID(Threads, barrier1, "$Id$")
+
+#if defined (ACE_HAS_THREADS)
+
+struct Tester_Args
+ // = TITLE
+ // These arguments are passed into each test thread.
+{
+ Tester_Args (ACE_Barrier &tb, int i)
+ : tester_barrier_ (tb),
+ n_iterations_ (i) {}
+
+ ACE_Barrier &tester_barrier_;
+ // Reference to the tester barrier. This controls each miteration of
+ // the tester function running in every thread.
+
+ int n_iterations_;
+ // Number of iterations to run.
+};
+
+// Iterate <n_iterations> time printing off a message and "waiting"
+// for all other threads to complete this iteration.
+
+static void *
+tester (Tester_Args *args)
+{
+ for (int iterations = 1;
+ iterations <= args->n_iterations_;
+ iterations++)
+ {
+ ACE_DEBUG ((LM_DEBUG, "(%t) in iteration %d\n", iterations));
+
+ // Block until all other threads have waited, then continue.
+ args->tester_barrier_.wait ();
+ }
+
+ return 0;
+}
+
+// Default number of threads to spawn.
+static const int DEFAULT_ITERATIONS = 5;
+
+int
+ACE_TMAIN (int argc, ACE_TCHAR *argv[])
+{
+ ACE_Service_Config daemon (argv[0]);
+
+ int n_threads = argc > 1 ? ACE_OS::atoi (argv[1]) : ACE_DEFAULT_THREADS;
+ int n_iterations = argc > 2 ? ACE_OS::atoi (argv[2]) : DEFAULT_ITERATIONS;
+
+ ACE_Barrier tester_barrier (n_threads);
+
+ Tester_Args args (tester_barrier, n_iterations);
+
+ if (ACE_Thread_Manager::instance ()->spawn_n
+ (int(n_threads), ACE_THR_FUNC (tester),
+ (void *) &args, THR_NEW_LWP | THR_DETACHED) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "spawn_n"), 1);
+
+ // Wait for all the threads to reach their exit point.
+ ACE_Thread_Manager::instance ()->wait ();
+
+ ACE_DEBUG ((LM_DEBUG, "(%t) done\n"));
+ return 0;
+}
+#else
+int
+ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ ACE_ERROR ((LM_ERROR, "threads not supported on this platform\n"));
+ return 0;
+}
+#endif /* ACE_HAS_THREADS */
diff --git a/ACE/examples/Threads/barrier2.cpp b/ACE/examples/Threads/barrier2.cpp
new file mode 100644
index 00000000000..cd322b82856
--- /dev/null
+++ b/ACE/examples/Threads/barrier2.cpp
@@ -0,0 +1,316 @@
+// $Id$
+
+// This test program illustrates how the ACE task workers/barrier
+// synchronization mechanisms work in conjunction with the ACE_Task
+// and the ACE_Thread_Manager. The manual flag not set simulates user
+// input, if set input comes from stdin until RETURN only is entered
+// which stops all workers via a message block of length 0. This is an
+// alernative shutdown of workers compared to queue deactivate. The
+// delay_put flag simulates a delay between the shutdown puts. All
+// should work with this flag disabled! The BARRIER_TYPE is supposed
+// to enable/disable barrier sync on each svc a worker has done.
+
+#include "ace/OS_NS_string.h"
+#include "ace/OS_NS_unistd.h"
+#include "ace/OS_main.h"
+#include "ace/Task.h"
+#include "ace/Service_Config.h"
+
+ACE_RCSID(Threads, barrier2, "$Id$")
+
+#if defined (ACE_HAS_THREADS)
+
+#include "ace/Null_Barrier.h"
+#define BARRIER_TYPE ACE_Null_Barrier
+
+template <class BARRIER>
+class Worker_Task : public ACE_Task<ACE_MT_SYNCH>
+{
+public:
+ Worker_Task (ACE_Thread_Manager *thr_mgr,
+ int n_threads,
+ int inp_serialize = 1);
+
+ virtual int producer (void);
+ // produce input for workers
+
+ virtual int input (ACE_Message_Block *mb);
+ // Fill one message block via a certain input strategy.
+
+ virtual int output (ACE_Message_Block *mb);
+ // Forward one message block via a certain output strategy to the
+ // next task if any.
+
+ virtual int service (ACE_Message_Block *mb, int iter);
+ // Perform one message block dependant service.
+
+private:
+ virtual int put (ACE_Message_Block *mb, ACE_Time_Value *tv=0);
+
+ virtual int svc (void);
+ // Iterate <n_iterations> time printing off a message and "waiting"
+ // for all other threads to complete this iteration.
+
+ // = Not needed for this test.
+ virtual int open (void *) { return 0; }
+ virtual int close (u_long)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ "(%t) in close of worker\n"));
+ return 0;
+ }
+
+ int nt_;
+ // Number of worker threads to run.
+
+ int inp_serialize_;
+
+ BARRIER barrier_;
+};
+
+template <class BARRIER>
+Worker_Task<BARRIER>::Worker_Task (ACE_Thread_Manager *thr_mgr,
+ int n_threads,
+ int inp_serialize)
+ : ACE_Task<ACE_MT_SYNCH> (thr_mgr),
+ barrier_ (n_threads)
+{
+ nt_ = n_threads;
+
+ // Create worker threads.
+ inp_serialize_ = inp_serialize;
+
+ // Use the task's message queue for serialization (default) or run
+ // service in the context of the caller thread.
+
+ if (nt_ > 0 && inp_serialize == 1)
+ if (this->activate (THR_NEW_LWP, n_threads) == -1)
+ ACE_ERROR ((LM_ERROR,
+ "%p\n",
+ "activate failed"));
+}
+
+// Simply enqueue the Message_Block into the end of the queue.
+
+template <class BARRIER> int
+Worker_Task<BARRIER>::put (ACE_Message_Block *mb,
+ ACE_Time_Value *tv)
+{
+ int result;
+
+ if (this->inp_serialize_)
+ result = this->putq (mb, tv);
+ else
+ {
+ static int iter = 0;
+ result = this->service (mb, iter++);
+
+ if (this->output (mb) < 0)
+ ACE_DEBUG ((LM_DEBUG,
+ "(%t) output not connected!\n"));
+
+ mb->release ();
+ }
+ return result;
+}
+
+template <class BARRIER> int
+Worker_Task<BARRIER>::service (ACE_Message_Block *mb,
+ int iter)
+{
+ size_t length = mb->length ();
+
+ if (length > 0)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ "(%t) in iteration %d len=%d text got:\n",
+ iter,
+ length));
+ ACE_OS::write (ACE_STDOUT,
+ mb->rd_ptr (),
+ length);
+ ACE_DEBUG ((LM_DEBUG,
+ "\n"));
+ }
+ return 0;
+}
+
+// Iterate <n_iterations> time printing off a message and "waiting"
+// for all other threads to complete this iteration.
+
+template <class BARRIER> int
+Worker_Task<BARRIER>::svc (void)
+{
+ // Note that the <ACE_Task::svc_run> method automatically adds us to
+ // the Thread_Manager when the thread begins.
+
+ // Keep looping, reading a message out of the queue, until we get a
+ // message with a length == 0, which signals us to quit.
+
+ for (int iter = 1; ;iter++)
+ {
+ ACE_Message_Block *mb = 0;
+
+ int result = this->getq (mb);
+
+ if (result == -1)
+ {
+ ACE_ERROR ((LM_ERROR,
+ "(%t) in iteration %d\n",
+ "error waiting for message in iteration",
+ iter));
+ break;
+ }
+
+ size_t length = mb->length ();
+ this->service (mb,iter);
+
+ if (length == 0)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ "(%t) in iteration %d got quit, exit!\n",
+ iter));
+ mb->release ();
+ break;
+ }
+
+ this->barrier_.wait ();
+ this->output (mb);
+
+ mb->release ();
+ }
+
+ // Note that the <ACE_Task::svc_run> method automatically removes us
+ // from the Thread_Manager when the thread exits.
+
+ return 0;
+}
+
+template <class BARRIER> int
+Worker_Task<BARRIER>::producer (void)
+{
+ // Keep reading stdin, until we reach EOF.
+
+ for (;;)
+ {
+ // Allocate a new message.
+ ACE_Message_Block *mb;
+
+ ACE_NEW_RETURN (mb,
+ ACE_Message_Block (BUFSIZ),
+ -1);
+
+ if (this->input (mb) == -1)
+ return -1;
+ }
+
+ ACE_NOTREACHED (return 0);
+}
+
+template <class BARRIER> int
+Worker_Task<BARRIER>::output (ACE_Message_Block *mb)
+{
+ return this->put_next (mb);
+}
+
+template <class BARRIER> int
+Worker_Task<BARRIER>::input (ACE_Message_Block *mb)
+{
+ ACE_Message_Block *mb1;
+
+#if !defined (manual)
+ static int l = 0;
+ char str[] = "kalle";
+ ACE_OS::strcpy (mb->rd_ptr (), str);
+
+ size_t n = ACE_OS::strlen (str);
+
+ if (l == 1000)
+ n = 1;
+ l++;
+
+ if (l == 0 || (l % 100 == 0))
+ ACE_OS::sleep (5);
+ if (n <= 1)
+#else
+ ACE_DEBUG ((LM_DEBUG,
+ "(%t) press chars and enter to put a new message into task queue ...\n"));
+ n = ACE_OS::read (ACE_STDIN,
+ mb->rd_ptr (),
+ mb->size ());
+ if (n <= 1)
+#endif /* manual */
+ {
+ // Send a shutdown message to the waiting threads and exit.
+ // cout << "\nvor loop, dump of task msg queue:\n" << endl;
+ // this->msg_queue ()->dump ();
+
+ for (int i = 0; i < nt_; i++)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ "(%t) eof, sending block for thread=%d\n",
+ i + 1));
+
+ ACE_NEW_RETURN (mb1,
+ ACE_Message_Block (2),
+ -1);
+ mb1->length (0);
+
+ if (this->put (mb1) == -1)
+ ACE_ERROR ((LM_ERROR,
+ "(%t) %p\n",
+ "put"));
+#if defined (delay_put)
+ // this sleep helps to shutdown correctly -> was an error!
+ ACE_OS::sleep (1);
+#endif /* delay_put */
+ }
+ return -1;
+ }
+ else
+ {
+ // Send a normal message to the waiting threads and continue
+ // producing.
+ mb->wr_ptr (n);
+
+ if (this->put (mb) == -1)
+ ACE_ERROR ((LM_ERROR,
+ "(%t) %p\n",
+ "put"));
+ }
+ return 0;
+}
+
+int
+ACE_TMAIN (int argc, ACE_TCHAR *argv[])
+{
+ int n_threads = argc > 1 ? ACE_OS::atoi (argv[1]) : ACE_DEFAULT_THREADS;
+
+ ACE_DEBUG ((LM_DEBUG,
+ "(%t) worker threads running=%d\n",
+ n_threads));
+
+ Worker_Task<BARRIER_TYPE> worker_task (ACE_Thread_Manager::instance (),
+ /* n_threads */ 0,
+ 0);
+ worker_task.producer ();
+
+ // Wait for all the threads to reach their exit point.
+ ACE_DEBUG ((LM_DEBUG,
+ "(%t) waiting with thread manager ...\n"));
+
+ ACE_Thread_Manager::instance ()->wait ();
+
+ ACE_DEBUG ((LM_DEBUG,
+ "(%t) done correct!\n"));
+ return 0;
+}
+
+#else
+int
+ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ ACE_ERROR ((LM_ERROR, "threads not supported on this platform\n"));
+ return 0;
+}
+#endif /* ACE_HAS_THREADS */
diff --git a/ACE/examples/Threads/cancel.cpp b/ACE/examples/Threads/cancel.cpp
new file mode 100644
index 00000000000..f10bb822580
--- /dev/null
+++ b/ACE/examples/Threads/cancel.cpp
@@ -0,0 +1,86 @@
+// $Id$
+
+// Test out the cooperative thread cancellation mechanisms provided by
+// the ACE_Thread_Manager.
+
+#include "ace/OS_NS_unistd.h"
+#include "ace/OS_main.h"
+#include "ace/Service_Config.h"
+#include "ace/Thread_Manager.h"
+
+ACE_RCSID(Threads, cancel, "$Id$")
+
+#if defined (ACE_HAS_THREADS)
+
+static void *
+#if ACE_SIZEOF_VOID_P==8 && ACE_SIZEOF_INT<ACE_SIZEOF_VOID_P
+worker (long iterations)
+{
+ for (long i = 0; i < iterations; i++)
+#else
+worker (int iterations)
+{
+ for (int i = 0; i < iterations; i++)
+#endif
+ {
+ if ((i % 10) == 0
+ && (ACE_Thread_Manager::instance ()->testcancel (ACE_Thread::self ()) != 0))
+ {
+ ACE_DEBUG ((LM_DEBUG, "(%t) has been cancelled before iteration!\n", i));
+ break;
+ }
+ }
+
+ return 0;
+}
+
+static const int DEFAULT_THREADS = ACE_DEFAULT_THREADS;
+static const int DEFAULT_ITERATIONS = 100000;
+
+int
+ACE_TMAIN (int argc, ACE_TCHAR *argv[])
+{
+ ACE_Service_Config daemon;
+
+ daemon.open (argv[0]);
+
+ int n_threads = argc > 1 ? ACE_OS::atoi (argv[1]) : DEFAULT_THREADS;
+#if ACE_SIZEOF_VOID_P==8 && ACE_SIZEOF_INT<ACE_SIZEOF_VOID_P
+ long n_iterations = (long)( argc > 2 ? ACE_OS::atoi (argv[2]) : DEFAULT_ITERATIONS );
+#else
+ int n_iterations = argc > 2 ? ACE_OS::atoi (argv[2]) : DEFAULT_ITERATIONS;
+#endif
+
+ ACE_Thread_Manager *thr_mgr = ACE_Thread_Manager::instance ();
+
+ int grp_id = thr_mgr->spawn_n (n_threads, ACE_THR_FUNC (worker),
+ (void *) n_iterations,
+ THR_NEW_LWP | THR_DETACHED);
+
+ // Wait for 2 seconds and then suspend every thread in the group.
+ ACE_OS::sleep (2);
+ thr_mgr->suspend_grp (grp_id);
+
+ // Wait for 2 more seconds and then resume every thread in the
+ // group.
+ ACE_OS::sleep (ACE_Time_Value (2));
+ thr_mgr->resume_grp (grp_id);
+
+ // Wait for 2 more seconds and then send a SIGINT to every thread in
+ // the group.
+ ACE_OS::sleep (ACE_Time_Value (2));
+ thr_mgr->kill_grp (grp_id, SIGINT);
+
+ // Wait for 2 more seconds and then exit (which should kill all the
+ // threads)!
+ ACE_OS::sleep (ACE_Time_Value (2));
+
+ return 0;
+}
+#else
+int
+ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ ACE_ERROR_RETURN ((LM_ERROR, "threads not supported on this platform\n"), -1);
+}
+#endif /* ACE_HAS_THREADS */
diff --git a/ACE/examples/Threads/future1.cpp b/ACE/examples/Threads/future1.cpp
new file mode 100644
index 00000000000..7b95e549431
--- /dev/null
+++ b/ACE/examples/Threads/future1.cpp
@@ -0,0 +1,404 @@
+// $Id$
+
+// ============================================================================
+//
+// = LIBRARY
+// tests
+//
+// = FILENAME
+// Test_Future.cpp
+//
+// = DESCRIPTION
+// This example tests the ACE Future.
+//
+// = AUTHOR
+// Andres Kruse <Andres.Kruse@cern.ch> and Douglas C. Schmidt
+// <schmidt@cs.wustl.edu>
+//
+// ============================================================================
+
+#include "ace/OS_NS_string.h"
+#include "ace/OS_NS_unistd.h"
+#include "ace/OS_main.h"
+#include "ace/ACE.h"
+#include "ace/Task.h"
+#include "ace/Thread_Mutex.h"
+#include "ace/Message_Queue.h"
+#include "ace/Future.h"
+#include "ace/Method_Request.h"
+#include "ace/Activation_Queue.h"
+#include "ace/Auto_Ptr.h"
+#include "ace/Atomic_Op.h"
+
+ACE_RCSID(Threads, future1, "$Id$")
+
+#if defined (ACE_HAS_THREADS)
+
+typedef ACE_Atomic_Op<ACE_Thread_Mutex, int> ATOMIC_INT;
+
+// a counter for the tasks..
+static ATOMIC_INT task_count (0);
+
+// a counter for the futures..
+static ATOMIC_INT future_count (0);
+static ATOMIC_INT future_no (0);
+
+// a counter for the capsules..
+static ATOMIC_INT capsule_count (0);
+static ATOMIC_INT capsule_no (0);
+
+// a counter for the method objects...
+static ATOMIC_INT methodobject_count (0);
+static ATOMIC_INT methodobject_no (0);
+
+class Scheduler : public ACE_Task_Base
+ // = TITLE
+ // Active Object Scheduler.
+{
+ friend class Method_RequestWork;
+public:
+ Scheduler (const char *, Scheduler * = 0);
+ virtual ~Scheduler (void);
+
+ virtual int open (void *args = 0);
+ virtual int close (u_long flags = 0);
+ virtual int svc (void);
+
+ ACE_Future<u_long> work (u_long param, int count = 1);
+ ACE_Future<const char*> name (void);
+ void end (void);
+
+ u_long work_i (u_long, int);
+ const char *name_i (void);
+
+private:
+ char *name_;
+ ACE_Activation_Queue activation_queue_;
+ Scheduler *scheduler_;
+};
+
+class Method_Request_work : public ACE_Method_Request
+ // = TITLE
+ // Reification of the <work> method.
+{
+public:
+ Method_Request_work (Scheduler *, u_long, int, ACE_Future<u_long> &);
+ virtual ~Method_Request_work (void);
+ virtual int call (void);
+
+private:
+ Scheduler *scheduler_;
+ u_long param_;
+ int count_;
+ ACE_Future<u_long> future_result_;
+};
+
+Method_Request_work::Method_Request_work (Scheduler* new_Scheduler,
+ u_long new_param,
+ int new_count,
+ ACE_Future<u_long> &new_result)
+ : scheduler_ (new_Scheduler),
+ param_ (new_param),
+ count_ (new_count),
+ future_result_ (new_result)
+{
+ ACE_DEBUG ((LM_DEBUG,
+ "(%t) Method_Request_work created\n"));
+}
+
+Method_Request_work::~Method_Request_work (void)
+{
+ ACE_DEBUG ((LM_DEBUG, "(%t) Method_Request_work will be deleted.\n"));
+}
+
+
+int
+Method_Request_work::call (void)
+{
+ return this->future_result_.set (this->scheduler_->work_i (this->param_, this->count_));
+}
+
+class Method_Request_name : public ACE_Method_Request
+ // = TITLE
+ // Reification of the <name> method.
+{
+public:
+ Method_Request_name (Scheduler *, ACE_Future<const char*> &);
+ virtual ~Method_Request_name (void);
+ virtual int call (void);
+
+private:
+ Scheduler *scheduler_;
+ ACE_Future<const char *> future_result_;
+};
+
+Method_Request_name::Method_Request_name (Scheduler *new_scheduler,
+ ACE_Future<const char *> &new_result)
+ : scheduler_ (new_scheduler),
+ future_result_ (new_result)
+{
+ ACE_DEBUG ((LM_DEBUG,
+ "(%t) Method_Request_name created\n"));
+}
+
+Method_Request_name::~Method_Request_name (void)
+{
+ ACE_DEBUG ((LM_DEBUG,
+ "(%t) Method_Request_name will be deleted.\n"));
+}
+
+int
+Method_Request_name::call (void)
+{
+ return future_result_.set (scheduler_->name_i ());
+}
+
+class Method_Request_end : public ACE_Method_Request
+ // = TITLE
+ // Reification of the <end> method.
+{
+public:
+ Method_Request_end (Scheduler *new_scheduler): scheduler_ (new_scheduler) {}
+ virtual ~Method_Request_end (void) {}
+ virtual int call (void) { return -1; }
+
+private:
+ Scheduler *scheduler_;
+ // Keep track of our scheduler.
+};
+
+// Constructor.
+Scheduler::Scheduler (const char *newname,
+ Scheduler *new_scheduler)
+{
+ ACE_NEW (this->name_, char[ACE_OS::strlen (newname) + 1]);
+ ACE_OS::strcpy (this->name_, newname);
+ this->scheduler_ = new_scheduler;
+ ACE_DEBUG ((LM_DEBUG, "(%t) Scheduler %s created\n", this->name_));
+}
+
+// Destructor
+Scheduler::~Scheduler (void)
+{
+ ACE_DEBUG ((LM_DEBUG, "(%t) Scheduler %s will be destroyed\n", this->name_));
+ delete [] this->name_;
+}
+
+// open
+int
+Scheduler::open (void *)
+{
+ task_count++;
+ ACE_DEBUG ((LM_DEBUG, "(%t) Scheduler %s open\n", this->name_));
+ return this->activate (THR_BOUND);
+}
+
+// close
+int
+Scheduler::close (u_long)
+{
+ ACE_DEBUG ((LM_DEBUG, "(%t) Scheduler %s close\n", this->name_));
+ task_count--;
+ return 0;
+}
+
+// service..
+int
+Scheduler::svc (void)
+{
+ for (;;)
+ {
+ // Dequeue the next method object (we use an auto pointer in
+ // case an exception is thrown in the <call>).
+ auto_ptr<ACE_Method_Request> mo (this->activation_queue_.dequeue ());
+
+ ACE_DEBUG ((LM_DEBUG, "(%t) calling method object\n"));
+ // Call it.
+ if (mo->call () == -1)
+ break;
+ // Destructor automatically deletes it.
+ }
+
+ /* NOTREACHED */
+ return 0;
+}
+
+void
+Scheduler::end (void)
+{
+ this->activation_queue_.enqueue (new Method_Request_end (this));
+}
+
+
+// Here's where the Work takes place.
+u_long
+Scheduler::work_i (u_long param,
+ int count)
+{
+ ACE_UNUSED_ARG (count);
+
+ return ACE::is_prime (param, 2, param / 2);
+}
+
+const char *
+Scheduler::name_i (void)
+{
+ char *the_name;
+
+ ACE_NEW_RETURN (the_name, char[ACE_OS::strlen (this->name_) + 1], 0);
+ ACE_OS::strcpy (the_name, this->name_);
+
+ return the_name;
+}
+
+ACE_Future<const char *>
+Scheduler::name (void)
+{
+ if (this->scheduler_)
+ // Delegate to the Scheduler.
+ return this->scheduler_->name ();
+ else
+ {
+ ACE_Future<const char*> new_future;
+
+ // @@ What happens if new fails here?
+ this->activation_queue_.enqueue
+ (new Method_Request_name (this, new_future));
+
+ return new_future;
+ }
+}
+
+ACE_Future<u_long>
+Scheduler::work (u_long newparam,
+ int newcount)
+{
+ if (this->scheduler_) {
+ return this->scheduler_->work (newparam, newcount);
+ }
+ else {
+ ACE_Future<u_long> new_future;
+
+ this->activation_queue_.enqueue
+ (new Method_Request_work (this, newparam, newcount, new_future));
+ return new_future;
+ }
+}
+
+// @@ These values should be set by the command line options!
+
+// Total number of loops.
+static size_t n_loops = 100;
+
+int
+ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ Scheduler *andres, *peter, *helmut, *matias;
+
+ // Create active objects..
+ // @@ Should "open" be subsumed within the constructor of
+ // Scheduler()?
+ ACE_NEW_RETURN (andres, Scheduler ("andres"), -1);
+ andres->open ();
+ ACE_NEW_RETURN (peter, Scheduler ("peter"), -1);
+ peter->open ();
+ ACE_NEW_RETURN (helmut, Scheduler ("helmut"), -1);
+ helmut->open ();
+
+ // Matias passes all asynchronous method calls on to Andres...
+ ACE_NEW_RETURN (matias, Scheduler ("matias", andres), -1);
+ matias->open ();
+
+ for (size_t i = 0; i < n_loops; i++)
+ {
+ {
+ ACE_Future<u_long> fresulta, fresultb, fresultc, fresultd, fresulte;
+ ACE_Future<const char *> fname;
+
+ ACE_DEBUG ((LM_DEBUG, "(%t) going to do a non-blocking call\n"));
+
+ fresulta = andres->work (9013);
+ fresultb = peter->work (9013);
+ fresultc = helmut->work (9013);
+ fresultd = matias->work (9013);
+ fname = andres->name ();
+
+ // see if the result is available...
+ if (fresulta.ready ())
+ ACE_DEBUG ((LM_DEBUG, "(%t) wow.. work is ready.....\n"));
+
+ ACE_DEBUG ((LM_DEBUG, "(%t) non-blocking call done... now blocking...\n"));
+
+ // Save the result of fresulta.
+
+ fresulte = fresulta;
+
+ if (i % 3 == 0)
+ {
+ // Every 3rd time... disconnect the futures...
+ // but "fresulte" should still contain the result...
+ fresulta.cancel (10);
+ fresultb.cancel (20);
+ fresultc.cancel (30);
+ fresultd.cancel (40);
+ }
+
+ u_long resulta = 0, resultb = 0, resultc = 0, resultd = 0, resulte = 0;
+
+ fresulta.get (resulta);
+ fresultb.get (resultb);
+ fresultc.get (resultc);
+ fresultd.get (resultd);
+ fresulte.get (resulte);
+
+ ACE_DEBUG ((LM_DEBUG, "(%t) result a %u\n", (u_int) resulte));
+ ACE_DEBUG ((LM_DEBUG, "(%t) result b %u\n", (u_int) resulta));
+ ACE_DEBUG ((LM_DEBUG, "(%t) result c %u\n", (u_int) resultb));
+ ACE_DEBUG ((LM_DEBUG, "(%t) result d %u\n", (u_int) resultc));
+ ACE_DEBUG ((LM_DEBUG, "(%t) result e %u\n", (u_int) resultd));
+
+ const char *name = 0;
+
+ fname.get (name);
+
+ ACE_DEBUG ((LM_DEBUG, "(%t) name %s\n", name));
+ delete [] (char *) name;
+ }
+
+ ACE_DEBUG ((LM_DEBUG,
+ "(%t) task_count %d future_count %d capsule_count %d methodobject_count %d\n",
+ task_count.value (),
+ future_count.value (),
+ capsule_count.value (),
+ methodobject_count.value ()));
+ }
+
+ // Close things down.
+ andres->end ();
+ peter->end ();
+ helmut->end ();
+ matias->end ();
+
+ ACE_OS::sleep (2);
+
+ ACE_DEBUG ((LM_DEBUG,
+ "(%t) task_count %d future_count %d capsule_count %d methodobject_count %d\n",
+ task_count.value (),
+ future_count.value (),
+ capsule_count.value (),
+ methodobject_count.value ()));
+
+ ACE_DEBUG ((LM_DEBUG,"(%t) th' that's all folks!\n"));
+
+ ACE_OS::sleep (5);
+ return 0;
+}
+
+#else
+int
+ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ ACE_ERROR ((LM_ERROR, "threads not supported on this platform\n"));
+ return 0;
+}
+#endif /* ACE_HAS_THREADS */
diff --git a/ACE/examples/Threads/future2.cpp b/ACE/examples/Threads/future2.cpp
new file mode 100644
index 00000000000..4bb9519ca28
--- /dev/null
+++ b/ACE/examples/Threads/future2.cpp
@@ -0,0 +1,525 @@
+// $Id$
+
+// ============================================================================
+//
+// = LIBRARY
+// tests
+//
+// = FILENAME
+// Test_Future.cpp
+//
+// = DESCRIPTION
+// This example tests the ACE Future.
+//
+// = AUTHOR
+// Andres Kruse <Andres.Kruse@cern.ch> and Douglas C. Schmidt
+// <schmidt@cs.wustl.edu>
+//
+// Modification History
+// Aug. 96; A.Kruse; dev.
+// Aug. 96; D.Schmidt; complete workover
+// 08/27/96; A.Kruse; - the friends of Scheduler are "Method_Request_name"
+// and "Method_Request_work".
+// - make the methods "work_i" and "name_i" private
+// 09/2/96; D.Schmidt; Integrate with new ACE_Future API and rearrange
+// the tests so they are more modular.
+// ============================================================================
+
+#include "ace/OS_NS_string.h"
+#include "ace/OS_NS_sys_time.h"
+#include "ace/OS_NS_unistd.h"
+#include "ace/OS_main.h"
+#include "ace/ACE.h"
+#include "ace/Task.h"
+#include "ace/Message_Queue.h"
+#include "ace/Future.h"
+#include "ace/Method_Request.h"
+#include "ace/Activation_Queue.h"
+#include "ace/Auto_Ptr.h"
+#include "ace/Atomic_Op.h"
+
+ACE_RCSID(Threads, future2, "$Id$")
+#if defined (ACE_HAS_THREADS)
+
+typedef ACE_Atomic_Op<ACE_Thread_Mutex, int> ATOMIC_INT;
+
+// a counter for the tasks..
+static ATOMIC_INT scheduler_open_count (0);
+
+// forward declarations
+class Method_Request_work;
+class Method_Request_name;
+
+class Scheduler : public ACE_Task_Base
+ // = TITLE
+ // Active Object Scheduler.
+{
+ // Every method object has to be able to access the private methods.
+
+ friend class Method_Request_work;
+ friend class Method_Request_name;
+ friend class Method_Request_end;
+public:
+
+ Scheduler (const char *, Scheduler * = 0);
+ virtual ~Scheduler (void);
+
+ virtual int open (void *args = 0);
+ // The method that is used to start the active object.
+
+ // = Here are the methods exported by the class. They return an
+ // <ACE_Future>.
+ ACE_Future<u_long> work (u_long param, int count = 1);
+ ACE_Future<char*> name (void);
+ void end (void);
+
+private:
+ virtual int close (u_long flags = 0);
+ // Should not be accessible from outside... (use end () instead).
+
+ virtual int svc (void);
+ // Here the actual servicing of all requests is happening..
+
+ // = Implementation methods.
+ u_long work_i (u_long, int);
+ char *name_i (void);
+
+ char *name_;
+ ACE_Activation_Queue activation_queue_;
+ Scheduler *scheduler_;
+};
+
+class Method_Request_work : public ACE_Method_Request
+ // = TITLE
+ // Reification of the <work> method.
+{
+public:
+ Method_Request_work (Scheduler *, u_long, int, ACE_Future<u_long> &);
+ virtual ~Method_Request_work (void);
+ virtual int call (void);
+
+private:
+ Scheduler *scheduler_;
+ u_long param_;
+ int count_;
+ ACE_Future<u_long> future_result_;
+};
+
+Method_Request_work::Method_Request_work (Scheduler* new_Scheduler,
+ u_long new_param,
+ int new_count,
+ ACE_Future<u_long> &new_result)
+ : scheduler_ (new_Scheduler),
+ param_ (new_param),
+ count_ (new_count),
+ future_result_ (new_result)
+{
+}
+
+Method_Request_work::~Method_Request_work (void)
+{
+}
+
+int
+Method_Request_work::call (void)
+{
+ return this->future_result_.set (this->scheduler_->work_i (this->param_, this->count_));
+}
+
+class Method_Request_name : public ACE_Method_Request
+ // = TITLE
+ // Reification of the <name> method.
+{
+public:
+ Method_Request_name (Scheduler *, ACE_Future<char*> &);
+ virtual ~Method_Request_name (void);
+ virtual int call (void);
+
+private:
+ Scheduler *scheduler_;
+ ACE_Future<char*> future_result_;
+};
+
+
+Method_Request_name::Method_Request_name (Scheduler *new_scheduler,
+ ACE_Future<char*> &new_result)
+ : scheduler_ (new_scheduler),
+ future_result_ (new_result)
+{
+ ACE_DEBUG ((LM_DEBUG,
+ " (%t) Method_Request_name created\n"));
+}
+
+Method_Request_name::~Method_Request_name (void)
+{
+ ACE_DEBUG ((LM_DEBUG,
+ " (%t) Method_Request_name will be deleted.\n"));
+}
+
+int
+Method_Request_name::call (void)
+{
+ return future_result_.set (scheduler_->name_i ());
+}
+
+class Method_Request_end : public ACE_Method_Request
+ // = TITLE
+ // Reification of the <end> method.
+{
+public:
+ Method_Request_end (Scheduler *new_Scheduler): scheduler_ (new_Scheduler) {}
+ virtual ~Method_Request_end (void) {}
+ virtual int call (void) { return -1; }
+
+private:
+ Scheduler *scheduler_;
+ // Keep track of our scheduler.
+};
+
+// constructor
+Scheduler::Scheduler (const char *newname, Scheduler *new_Scheduler)
+{
+ ACE_NEW (this->name_, char[ACE_OS::strlen (newname) + 1]);
+ ACE_OS::strcpy ((char *) this->name_, newname);
+ this->scheduler_ = new_Scheduler;
+ ACE_DEBUG ((LM_DEBUG, " (%t) Scheduler %s created\n", this->name_));
+}
+
+// Destructor
+Scheduler::~Scheduler (void)
+{
+ ACE_DEBUG ((LM_DEBUG, " (%t) Scheduler %s will be destroyed\n", this->name_));
+}
+
+int
+Scheduler::open (void *)
+{
+ scheduler_open_count++;
+ ACE_DEBUG ((LM_DEBUG, " (%t) Scheduler %s open\n", this->name_));
+ return this->activate (THR_BOUND);
+}
+
+int
+Scheduler::close (u_long)
+{
+ ACE_DEBUG ((LM_DEBUG, " (%t) Scheduler %s close\n", this->name_));
+ scheduler_open_count--;
+ return 0;
+}
+
+int
+Scheduler::svc (void)
+{
+ // Main event loop for this active object.
+ for (;;)
+ {
+ // Dequeue the next method object (we use an auto pointer in
+ // case an exception is thrown in the <call>).
+ auto_ptr<ACE_Method_Request> mo (this->activation_queue_.dequeue ());
+
+ ACE_DEBUG ((LM_DEBUG, " (%t) calling method object\n"));
+ // Call it.
+ if (mo->call () == -1)
+ break;
+ // Smart pointer destructor automatically deletes mo.
+ }
+
+ /* NOTREACHED */
+ return 0;
+}
+
+void
+Scheduler::end (void)
+{
+ this->activation_queue_.enqueue (new Method_Request_end (this));
+}
+
+// Here's where the Work takes place.
+u_long
+Scheduler::work_i (u_long param,
+ int count)
+{
+ ACE_UNUSED_ARG (count);
+
+ return ACE::is_prime (param, 2, param / 2);
+}
+
+char *
+Scheduler::name_i (void)
+{
+ char *the_name;
+
+ ACE_NEW_RETURN (the_name, char[ACE_OS::strlen (this->name_) + 1], 0);
+ ACE_OS::strcpy (the_name, this->name_);
+
+ return the_name;
+}
+
+ACE_Future<char *>
+Scheduler::name (void)
+{
+ if (this->scheduler_)
+ // Delegate to the other scheduler
+ return this->scheduler_->name ();
+ else
+ {
+ ACE_Future<char*> new_future;
+
+ if (this->thr_count () == 0)
+ {
+ // This scheduler is inactive... so we execute the user
+ // request right away...
+
+ auto_ptr<ACE_Method_Request> mo (new Method_Request_name (this, new_future));
+
+ mo->call ();
+ // Smart pointer destructor automatically deletes mo.
+ }
+ else
+ // @@ What happens if new fails here?
+ this->activation_queue_.enqueue
+ (new Method_Request_name (this, new_future));
+
+ return new_future;
+ }
+}
+
+ACE_Future<u_long>
+Scheduler::work (u_long newparam, int newcount)
+{
+ if (this->scheduler_)
+ return this->scheduler_->work (newparam, newcount);
+ else
+ {
+ ACE_Future<u_long> new_future;
+
+ if (this->thr_count () == 0)
+ {
+ auto_ptr<ACE_Method_Request> mo
+ (new Method_Request_work (this, newparam, newcount, new_future));
+ mo->call ();
+ // Smart pointer destructor automatically deletes it.
+ }
+ else
+ this->activation_queue_.enqueue
+ (new Method_Request_work (this, newparam, newcount, new_future));
+
+ return new_future;
+ }
+}
+
+static int
+determine_iterations (void)
+{
+ int n_iterations;
+
+ ACE_DEBUG ((LM_DEBUG," (%t) determining the number of iterations...\n"));
+ Scheduler *worker_a;
+
+ ACE_NEW_RETURN (worker_a, Scheduler ("worker A"), -1);
+
+ ACE_Time_Value tstart (ACE_OS::gettimeofday ());
+ ACE_Time_Value tend (ACE_OS::gettimeofday ());
+
+ // Determine the number of iterations... we want so many that the
+ // work () takes about 1 second...
+
+ for (n_iterations = 1;
+ (tend.sec () - tstart.sec ()) < 1;
+ n_iterations *= 2)
+ {
+ tstart = ACE_OS::gettimeofday ();
+
+ worker_a->work (9013, n_iterations);
+
+ tend = ACE_OS::gettimeofday ();
+ }
+
+ ACE_DEBUG ((LM_DEBUG," (%t) n_iterations %d\n",
+ (int) n_iterations));
+
+ worker_a->end ();
+ // @@ Can we safely delete worker_a here?
+ return n_iterations;
+}
+
+static void
+test_active_object (int n_iterations)
+{
+ ACE_UNUSED_ARG (n_iterations);
+
+ ACE_DEBUG ((LM_DEBUG," (%t) testing active object pattern...\n"));
+ // A simple example for the use of the active object pattern and
+ // futures to return values from an active object.
+
+ Scheduler *worker_a;
+ Scheduler *worker_b;
+ Scheduler *worker_c;
+
+ ACE_NEW (worker_a, Scheduler ("worker A"));
+ ACE_NEW (worker_b, Scheduler ("worker B"));
+ // Have worker_c delegate his work to worker_a.
+ ACE_NEW (worker_c, Scheduler ("worker C", worker_a));
+
+ // loop 0:
+ // test the Schedulers when they are not active.
+ // now the method objects will be created but since
+ // there is no active thread they will also be
+ // immediately executed, in the "main" thread.
+ // loop 1:
+ // do the same test but with the schedulers
+ // activated
+ for (int i = 0; i < 2; i++)
+ {
+ if (i == 1)
+ {
+ worker_a->open ();
+ worker_b->open ();
+ worker_c->open ();
+ }
+
+ ACE_Future<u_long> fresulta = worker_a->work (9013);
+ ACE_Future<u_long> fresultb = worker_b->work (9013);
+ ACE_Future<u_long> fresultc = worker_c->work (9013);
+
+ if (i == 0)
+ {
+ if (!fresulta.ready ())
+ ACE_DEBUG ((LM_DEBUG," (%t) ERROR: worker A is should be ready!!!\n"));
+ if (!fresultb.ready ())
+ ACE_DEBUG ((LM_DEBUG," (%t) ERROR: worker B is should be ready!!!\n"));
+ if (!fresultc.ready ())
+ ACE_DEBUG ((LM_DEBUG," (%t) ERROR: worker C is should be ready!!!\n"));
+ }
+
+ // When the workers are active we will block here until the
+ // results are available.
+
+ u_long resulta = fresulta;
+ u_long resultb = fresultb;
+ u_long resultc = fresultc;
+
+ ACE_Future<char *> fnamea = worker_a->name ();
+ ACE_Future<char *> fnameb = worker_b->name ();
+ ACE_Future<char *> fnamec = worker_c->name ();
+
+ char *namea = fnamea;
+ char *nameb = fnameb;
+ char *namec = fnamec;
+
+ ACE_DEBUG ((LM_DEBUG, " (%t) result from %s %u\n",
+ namea, (u_int) resulta));
+ ACE_DEBUG ((LM_DEBUG, " (%t) result from %s %u\n",
+ nameb, (u_int) resultb));
+ ACE_DEBUG ((LM_DEBUG, " (%t) result from %s %u\n",
+ namec, (u_int) resultc));
+ }
+
+ ACE_DEBUG ((LM_DEBUG, " (%t) scheduler_open_count %d before end ()\n",
+ scheduler_open_count.value ()));
+
+ worker_a->end ();
+ worker_b->end ();
+ worker_c->end ();
+
+ ACE_DEBUG ((LM_DEBUG, " (%t) scheduler_open_count %d immediately after end ()\n",
+ scheduler_open_count.value ()));
+
+ ACE_OS::sleep (2);
+
+ ACE_DEBUG ((LM_DEBUG, " (%t) scheduler_open_count %d after waiting\n",
+ scheduler_open_count.value ()));
+ // @@ Can we safely delete worker_a, worker_b, and worker_c?
+}
+
+static void
+test_cancellation (int n_iterations)
+{
+ ACE_DEBUG ((LM_DEBUG," (%t) testing cancellation of a future...\n"));
+
+ // Now test the cancelling a future.
+
+ Scheduler *worker_a;
+ ACE_NEW (worker_a, Scheduler ("worker A"));
+ worker_a->open ();
+
+ ACE_Future<u_long> fresulta = worker_a->work (9013, n_iterations);
+
+ // save the result by copying the future
+ ACE_Future<u_long> fresultb = fresulta;
+
+ // now we cancel the first future.. but the
+ // calculation will still go on...
+ fresulta.cancel (10);
+
+ if (!fresulta.ready ())
+ ACE_DEBUG ((LM_DEBUG," (%t) ERROR: future A is should be ready!!!\n"));
+
+ u_long resulta = fresulta;
+
+ ACE_DEBUG ((LM_DEBUG, " (%t) cancelled result %u\n", (u_int) resulta));
+
+ if (resulta != 10)
+ ACE_DEBUG ((LM_DEBUG, " (%t) cancelled result should be 10!!\n", resulta));
+
+ resulta = fresultb;
+
+ ACE_DEBUG ((LM_DEBUG, " (%t) true result %u\n", (u_int) resulta));
+
+ worker_a->end ();
+ // @@ Can we safely delete worker_a here?
+}
+
+static void
+test_timeout (int n_iterations)
+{
+ ACE_DEBUG ((LM_DEBUG," (%t) testing timeout on waiting for the result...\n"));
+ Scheduler *worker_a;
+ ACE_NEW (worker_a, Scheduler ("worker A"));
+ worker_a->open ();
+
+ ACE_Future<u_long> fresulta = worker_a->work (9013, 2 * n_iterations);
+
+ // Should immediately return... and we should see an error...
+ ACE_Time_Value *delay;
+ ACE_NEW (delay, ACE_Time_Value (1));
+
+ u_long resulta = 0;
+ fresulta.get (resulta, delay);
+
+ if (fresulta.ready ())
+ ACE_DEBUG ((LM_DEBUG," (%t) ERROR: future A is should not be ready!!!\n"));
+ else
+ ACE_DEBUG ((LM_DEBUG," (%t) timed out on future A\n"));
+
+ // now we wait until we are done...
+ fresulta.get (resulta);
+ ACE_DEBUG ((LM_DEBUG, " (%t) result %u\n", (u_int) resulta));
+
+ worker_a->end ();
+ // @@ Can we safely delete worker_a here?
+}
+
+int
+ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ int n_iterations = determine_iterations ();
+
+ test_active_object (n_iterations);
+ test_cancellation (n_iterations);
+ test_timeout (n_iterations);
+
+ ACE_DEBUG ((LM_DEBUG," (%t) that's all folks!\n"));
+
+ ACE_OS::sleep (5);
+ return 0;
+}
+
+#else
+int
+ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ ACE_ERROR ((LM_ERROR, "threads not supported on this platform\n"));
+ return 0;
+}
+#endif /* ACE_HAS_THREADS */
diff --git a/ACE/examples/Threads/manual_event.cpp b/ACE/examples/Threads/manual_event.cpp
new file mode 100644
index 00000000000..c168c384191
--- /dev/null
+++ b/ACE/examples/Threads/manual_event.cpp
@@ -0,0 +1,114 @@
+// $Id$
+
+// The test shows the use of an ACE_Manual_Event to create a
+// Pseudo_Barrier. Multiple threads are created which do the
+// following:
+//
+// 1. work
+// 2. synch with other threads
+// 3. more work
+//
+// ACE_Manual_Event is use to synch with other
+// threads. ACE_Manual_Event::signal() is used for broadcasting.
+
+#include "ace/OS_NS_unistd.h"
+#include "ace/OS_main.h"
+#include "ace/Service_Config.h"
+#include "ace/Thread_Mutex.h"
+#include "ace/Manual_Event.h"
+#include "ace/Thread_Manager.h"
+#include "ace/Atomic_Op.h"
+
+ACE_RCSID(Threads, manual_event, "$Id$")
+
+#if defined (ACE_HAS_THREADS)
+static ACE_Atomic_Op <ACE_Thread_Mutex, int> amount_of_work = 0;
+
+class Pseudo_Barrier
+ // = TITLE
+ // A barrier class using ACE manual-reset events.
+ //
+ // = DESCRIPTION
+ // This is *not* a real barrier.
+ // Pseudo_Barrier is more like a ``one shot'' barrier.
+ // All waiters after the Nth waiter are allowed to go.
+ // The barrier does not reset after the Nth waiter.
+ // For an example of a real barrier, please see class ACE_Barrier.
+{
+public:
+ Pseudo_Barrier (u_long count);
+
+ int wait (void);
+
+private:
+ ACE_Atomic_Op <ACE_Thread_Mutex, int> counter_;
+ ACE_Manual_Event event_;
+};
+
+Pseudo_Barrier::Pseudo_Barrier (u_long count)
+ : counter_ (count)
+{
+}
+
+int
+Pseudo_Barrier::wait (void)
+{
+ if (--this->counter_ == 0)
+ return this->event_.signal ();
+ else
+ return this->event_.wait ();
+}
+
+static void *
+worker (void *arg)
+{
+ Pseudo_Barrier &thread_barrier = *(Pseudo_Barrier *) arg;
+
+ // work
+ ACE_DEBUG ((LM_DEBUG, "(%t) working (%d secs)\n", ++::amount_of_work));
+ ACE_OS::sleep (::amount_of_work.value ());
+
+ // synch with everybody else
+ ACE_DEBUG ((LM_DEBUG, "(%t) waiting to synch with others \n"));
+ thread_barrier.wait ();
+
+ // more work
+ ACE_DEBUG ((LM_DEBUG, "(%t) more work (%d secs)\n", ++::amount_of_work));
+ ACE_OS::sleep (::amount_of_work.value ());
+
+ ACE_DEBUG ((LM_DEBUG, "(%t) dying \n"));
+
+ return 0;
+}
+
+int
+ACE_TMAIN (int argc, ACE_TCHAR **argv)
+{
+ int n_threads = argc == 2 ? ACE_OS::atoi (argv[1]) : 5;
+
+ ACE_Thread_Manager &tm = *ACE_Thread_Manager::instance ();
+
+ // synch object shared by all threads
+ Pseudo_Barrier thread_barrier (n_threads);
+
+ // create workers
+ if (tm.spawn_n (n_threads, (ACE_THR_FUNC) worker, &thread_barrier) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, "thread creates for worker failed"), -1);
+
+ // wait for all workers to exit
+ if (tm.wait () == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, "thread wait failed"), -1);
+ else
+ ACE_DEBUG ((LM_ERROR, "graceful exit\n"));
+
+ return 0;
+}
+
+#else
+int
+ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ ACE_ERROR ((LM_ERROR, "threads not supported on this platform\n"));
+ return 0;
+}
+#endif /* ACE_HAS_THREADS */
diff --git a/ACE/examples/Threads/process_manager.cpp b/ACE/examples/Threads/process_manager.cpp
new file mode 100644
index 00000000000..b8c2455b469
--- /dev/null
+++ b/ACE/examples/Threads/process_manager.cpp
@@ -0,0 +1,296 @@
+// $Id$
+
+// ============================================================================
+//
+// = LIBRARY
+// examples/Threads/
+//
+// = FILENAME
+// process_manager.cpp
+//
+// = DESCRIPTION
+// Test out the mechanisms provided by the ACE_Process_Manager.
+// Using the global ACE_Process_Manager::instance(), we first spawn
+// some processes (re-invoke this program, and plain-old-fork on
+// systems that support it), and try the wait() functions.
+//
+// Then, we register the Process_Manager with
+// ACE_Reactor::instance() and spawn more processes, counting on the
+// autoreap to clean up.
+//
+// Specific-pid and generic exit-handler functions are also tested.
+//
+// = AUTHOR
+// Douglas C. Schmidt <schmidt@cs.wustl.edu> and
+// Dave Madden <dhm@mersenne.com>
+//
+// ============================================================================
+
+#include "ace/OS_NS_unistd.h"
+#include "ace/OS_main.h"
+#include "ace/Service_Config.h"
+#include "ace/Thread_Manager.h"
+#include "ace/Process_Manager.h"
+#include "ace/Get_Opt.h"
+
+ACE_RCSID(Threads, process_manager, "$Id$")
+
+class ExitHandler : public ACE_Event_Handler
+{
+public:
+ ExitHandler (const char *name);
+
+ virtual ~ExitHandler (void);
+ virtual int handle_exit (ACE_Process *proc);
+ virtual int handle_timeout (const ACE_Time_Value &tv,
+ const void *arg = 0);
+ virtual int handle_close (ACE_HANDLE handle,
+ ACE_Reactor_Mask close_mask);
+ // Called when object is removed from the <ACE_Reactor>.
+private:
+ const char *name_;
+};
+
+ExitHandler::ExitHandler (const char *name)
+ : ACE_Event_Handler (),
+ name_ (name)
+{
+}
+
+ExitHandler::~ExitHandler (void)
+{
+ ACE_DEBUG ((LM_DEBUG,
+ "(%P|%t@%T) ExitHandler \"%s\" destroyed\n",
+ name_));
+}
+
+int
+ExitHandler::handle_exit (ACE_Process *proc)
+{
+ ACE_DEBUG ((LM_DEBUG,
+ "(%P|%t@%T) ExitHandler \"%s\" handle_exit for pid %d status %d\n",
+ name_,
+ proc->getpid (),
+ proc->exit_code ()));
+ return 0;
+}
+
+int
+ExitHandler::handle_timeout(const ACE_Time_Value &,
+ const void *)
+{
+ static int tick_tock = 0;
+
+ ACE_DEBUG ((LM_DEBUG,
+ "(%P|%t@%T) \"%s\" %s\n",
+ name_,
+ ACE_ODD (tick_tock) ? "Tock" : "Tick"));
+ tick_tock++;
+ return 0;
+}
+
+int
+ExitHandler::handle_close (ACE_HANDLE,
+ ACE_Reactor_Mask)
+{
+ ACE_DEBUG ((LM_DEBUG,
+ "(%P|%t@%T) ExitHandler \"%s\" handle_close\n",
+ name_));
+ delete this;
+ return 0;
+}
+
+// Spin furiously <iterations> times, pausing every 100 cycles to
+// print a message and sleep for a few seconds.
+
+static void
+worker (size_t iterations)
+{
+ for (size_t i = 0;
+ i <= iterations;
+ i++)
+ if (i && (i % 100) == 0)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ "(%P|%t@%T) worker spinning furiously... (%u)\n",
+ i));
+ ACE_OS::sleep (1);
+ }
+
+ ACE_DEBUG ((LM_DEBUG,
+ "(%P|%t@%T) worker finished\n"));
+}
+
+static int n_iterations = 500;
+static int child = 0;
+static int exit_code = 0;
+
+// Parse the command-line arguments and set options.
+static void
+parse_args (int argc, ACE_TCHAR *argv[])
+{
+ ACE_Get_Opt get_opt (argc, argv, ACE_TEXT("i:e:cu"));
+
+ int c;
+
+ while ((c = get_opt ()) != -1)
+ switch (c)
+ {
+ case 'i':
+ n_iterations = ACE_OS::atoi (get_opt.opt_arg ());
+ break;
+ case 'e':
+ exit_code = ACE_OS::atoi (get_opt.opt_arg ());
+ break;
+ case 'c':
+ child = 1;
+ break;
+ case 'u':
+ default:
+ ACE_DEBUG ((LM_DEBUG, "usage:\n"
+ "-p <processes>\n"
+ "-i <iterations>\n"));
+ break;
+ }
+}
+
+// Use ACE_Process_Manager::instance() to spawn another copy of this
+// process.
+
+static pid_t
+respawn_self (const ACE_TCHAR *myname,
+ int iter,
+ int exit_code)
+{
+ ACE_Process_Options options;
+ options.command_line ("%s -c -i %d -e %d",
+ myname,
+ iter,
+ exit_code);
+ return ACE_Process_Manager::instance ()->spawn (options);
+}
+
+int
+ACE_TMAIN (int argc, ACE_TCHAR *argv[])
+{
+ ACE_Service_Config daemon;
+
+ daemon.open (argv[0]);
+
+ parse_args (argc, argv);
+
+ if (child)
+ {
+ worker (n_iterations);
+
+ ACE_OS::exit (exit_code);
+ }
+
+ ACE_DEBUG ((LM_DEBUG,
+ "(%P|%t@%T) Process_Manager test. Expect output from"
+ "2 or 3 processes...\n"));
+
+ ACE_Process_Manager::instance ()->register_handler
+ (new ExitHandler ("default"));
+
+ pid_t pid1 = respawn_self (argv[0],
+ n_iterations,
+ 111);
+ pid_t pid2 = respawn_self (argv[0],
+ n_iterations + 500,
+ 222);
+
+#if !defined (ACE_WIN32)
+ pid_t pid3 = ACE_OS::fork ();
+
+ if (!pid3)
+ {
+ worker (n_iterations);
+ return 999;
+ }
+#endif /* ACE_WIN32 */
+
+ ACE_Process_Manager::instance ()->register_handler (new ExitHandler ("specific"),
+ pid2);
+
+ if (pid1 == ACE_INVALID_PID || pid2 == ACE_INVALID_PID)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "(%P|%t) %p\n",
+ "start_n"),
+ 1);
+
+ ACE_DEBUG ((LM_DEBUG,
+ "(%P|%t@%T) Test parent waiting (synchronously, "
+ "up to 6 seconds) for children...\n"));
+
+ int result =
+ ACE_Process_Manager::instance ()->wait (ACE_Time_Value (6));
+
+ ACE_DEBUG ((LM_DEBUG,
+ "(%P|%t@%T) Test parent: %d processes left\n",
+ result));
+
+ if (result > 0)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ "(%P|%t@%T) Test parent waiting (synchronously, "
+ "indefinitely) for remaining children...\n"));
+ result =
+ ACE_Process_Manager::instance ()->wait ();
+ ACE_DEBUG ((LM_DEBUG,
+ "(%P|%t@%T) Test parent finished waiting: %d\n",
+ result));
+ }
+
+ ACE_DEBUG ((LM_DEBUG,
+ "(%P|%t@%T) Test parent: try auto-reap functions\n"));
+
+ ACE_Process_Manager::instance ()->open (ACE_Process_Manager::DEFAULT_SIZE,
+ ACE_Reactor::instance ());
+
+ pid1 = respawn_self (argv[0],
+ n_iterations + 200,
+ 333 );
+ pid2 = respawn_self (argv[0],
+ n_iterations + 500,
+ 444);
+
+#if !defined (ACE_WIN32)
+ pid3 = ACE_OS::fork ();
+
+ if (!pid3)
+ {
+ worker (n_iterations);
+ return 888;
+ }
+#endif /* ACE_WIN32 */
+
+ ExitHandler *main_thread_work = 0;
+ ACE_NEW_RETURN (main_thread_work,
+ ExitHandler ("main thread worker"),
+ 1);
+
+ ACE_Reactor::instance ()->schedule_timer (main_thread_work,
+ 0,
+ ACE_Time_Value (2),
+ ACE_Time_Value (1, 500000));
+ ACE_DEBUG ((LM_DEBUG,
+ "(%P|%t@%T) Test parent: expect several Processes "
+ "to be auto-detected over the next 30 seconds.\n"
+ "The main thread will do some other work, too.\n" ));
+
+ ACE_Time_Value briefly (30);
+
+ result = ACE_Reactor::run_event_loop (briefly);
+
+ ACE_DEBUG ((LM_DEBUG,
+ "(%P|%t@%T) Test parent: finished (%d) %d.%d. Close"
+ "Process_Manager...\n",
+ result,
+ briefly.sec (),
+ briefly.usec ()));
+
+ ACE_Process_Manager::instance ()->close ();
+
+ return 0;
+}
diff --git a/ACE/examples/Threads/process_mutex.cpp b/ACE/examples/Threads/process_mutex.cpp
new file mode 100644
index 00000000000..bbb03c08d0b
--- /dev/null
+++ b/ACE/examples/Threads/process_mutex.cpp
@@ -0,0 +1,75 @@
+// $Id$
+
+// This program tests ACE_Process_Mutexes. To run it, open 3 or 4
+// windows and run this program in each window...
+
+#include "ace/OS_main.h"
+#include "ace/OS_NS_unistd.h"
+#include "ace/Thread_Mutex.h"
+#include "ace/Signal.h"
+#include "ace/Log_Msg.h"
+#include "ace/Process_Mutex.h"
+
+ACE_RCSID(Threads, process_mutex, "$Id$")
+
+#if defined (ACE_HAS_THREADS)
+
+static sig_atomic_t done;
+
+extern "C" void
+handler (int)
+{
+ done = 1;
+}
+
+int
+ACE_TMAIN (int argc, ACE_TCHAR *argv[])
+{
+ const ACE_TCHAR *name = argc > 1 ? argv[1] : ACE_TEXT("hello");
+ int iterations = argc > 2 ? ACE_OS::atoi (argv[2]) : 100;
+
+ ACE_Process_Mutex pm (name);
+
+ // Register a signal handler.
+ ACE_Sig_Action sa ((ACE_SignalHandler) handler, SIGINT);
+ ACE_UNUSED_ARG (sa);
+
+ for (int i = 0; i < iterations && !done; i++)
+ {
+ ACE_DEBUG ((LM_DEBUG, "(%P|%t) = acquiring\n"));
+ if (pm.acquire () == -1)
+ ACE_DEBUG ((LM_DEBUG, "(%P|%t) = %p\n", "acquire failed"));
+ else
+ ACE_DEBUG ((LM_DEBUG, "(%P|%t) = acquired\n"));
+
+ ACE_OS::sleep (3);
+
+ if (pm.release () == -1)
+ ACE_DEBUG ((LM_DEBUG, "(%P|%t) = %p\n", "release failed"));
+ else
+ ACE_DEBUG ((LM_DEBUG, "(%P|%t) = released\n"));
+
+ if (pm.tryacquire () == -1)
+ ACE_DEBUG ((LM_DEBUG, "(%P|%t) = %p\n", "tryacquire failed"));
+ else
+ ACE_DEBUG ((LM_DEBUG, "(%P|%t) = tryacquire\n"));
+
+ if (pm.release () == -1)
+ ACE_DEBUG ((LM_DEBUG, "(%P|%t) = %p\n", "release failed"));
+ else
+ ACE_DEBUG ((LM_DEBUG, "(%P|%t) = released\n"));
+ }
+
+ if (argc > 2)
+ pm.remove ();
+ return 0;
+}
+#else
+int
+ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "ACE doesn't support support threads on this platform (yet)\n"),
+ -1);
+}
+#endif /* ACE_HAS_THREADS */
diff --git a/ACE/examples/Threads/process_semaphore.cpp b/ACE/examples/Threads/process_semaphore.cpp
new file mode 100644
index 00000000000..e7adbb6a3ac
--- /dev/null
+++ b/ACE/examples/Threads/process_semaphore.cpp
@@ -0,0 +1,63 @@
+// $Id$
+
+// This program tests ACE_Process_Semaphore. To run it, open 3 or 4
+// windows and run this program in each window...
+
+#include "ace/OS_main.h"
+#include "ace/OS_NS_unistd.h"
+#include "ace/Signal.h"
+#include "ace/Log_Msg.h"
+#include "ace/Process_Semaphore.h"
+#include "ace/OS_NS_stdlib.h"
+
+ACE_RCSID(Threads, process_semaphore, "$Id$")
+
+static sig_atomic_t done;
+
+extern "C" void
+handler (int)
+{
+ done = 1;
+}
+
+int
+ACE_TMAIN (int argc, ACE_TCHAR *argv[])
+{
+ const ACE_TCHAR *name = argc == 1 ? ACE_TEXT("hello") : argv[1];
+ int iterations = argc > 2 ? ACE_OS::atoi (argv[2]) : 100;
+
+ ACE_Process_Semaphore pm (1, name);
+
+ ACE_Sig_Action sa ((ACE_SignalHandler) handler, SIGINT);
+ ACE_UNUSED_ARG (sa);
+
+ for (int i = 0; i < iterations && !done; i++)
+ {
+ ACE_DEBUG ((LM_DEBUG, "(%P|%t) = acquiring\n"));
+ if (pm.acquire () == -1)
+ ACE_DEBUG ((LM_DEBUG, "(%P|%t) = %p\n", "acquire failed"));
+ else
+ ACE_DEBUG ((LM_DEBUG, "(%P|%t) = acquired\n"));
+
+ ACE_OS::sleep (3);
+
+ if (pm.release () == -1)
+ ACE_DEBUG ((LM_DEBUG, "(%P|%t) = %p\n", "release failed"));
+ else
+ ACE_DEBUG ((LM_DEBUG, "(%P|%t) = released\n"));
+
+ if (pm.tryacquire () == -1)
+ ACE_DEBUG ((LM_DEBUG, "(%P|%t) = %p\n", "tryacquire failed"));
+ else
+ ACE_DEBUG ((LM_DEBUG, "(%P|%t) = tryacquire\n"));
+
+ if (pm.release () == -1)
+ ACE_DEBUG ((LM_DEBUG, "(%P|%t) = %p\n", "release failed"));
+ else
+ ACE_DEBUG ((LM_DEBUG, "(%P|%t) = released\n"));
+ }
+
+ if (argc > 2)
+ pm.remove ();
+ return 0;
+}
diff --git a/ACE/examples/Threads/reader_writer.cpp b/ACE/examples/Threads/reader_writer.cpp
new file mode 100644
index 00000000000..5344ba4d5b4
--- /dev/null
+++ b/ACE/examples/Threads/reader_writer.cpp
@@ -0,0 +1,188 @@
+// $Id$
+
+// This test program verifies the functionality of the ACE_OS
+// implementation of readers/writer locks on Win32 and Posix pthreads.
+
+#include "ace/OS_main.h"
+#include "ace/Thread.h"
+#include "ace/Thread_Manager.h"
+#include "ace/Get_Opt.h"
+#include "ace/Atomic_Op.h"
+
+ACE_RCSID(Threads, reader_writer, "$Id$")
+
+#if defined (ACE_HAS_THREADS)
+
+#include "ace/Guard_T.h"
+#include "ace/RW_Mutex.h"
+
+// Default number of iterations.
+static int n_iterations = 1000;
+
+// Default number of loops.
+static int n_loops = 100;
+
+// Default number of readers.
+static int n_readers = 6;
+
+// Default number of writers.
+static int n_writers = 2;
+
+// Thread id of last writer.
+static ACE_thread_t shared_thr_id;
+
+// Lock for shared_thr_id.
+static ACE_RW_Mutex rw_mutex;
+
+// Count of the number of readers and writers.
+ACE_Atomic_Op<ACE_Thread_Mutex, int> current_readers, current_writers;
+
+// Thread manager
+static ACE_Thread_Manager thr_mgr;
+
+// Explain usage and exit.
+static void
+print_usage_and_die (void)
+{
+ ACE_DEBUG ((LM_DEBUG,
+ "usage: %n [-r n_readers] [-w n_writers] [-n iteration_count]\n"));
+ ACE_OS::exit (1);
+}
+
+// Parse the command-line arguments and set options.
+static void
+parse_args (int argc, ACE_TCHAR *argv[])
+{
+ ACE_Get_Opt get_opt (argc, argv, ACE_TEXT("r:w:n:l:"));
+
+ int c;
+
+ while ((c = get_opt ()) != -1)
+ switch (c)
+ {
+ case 'r':
+ n_readers = ACE_OS::atoi (get_opt.opt_arg ());
+ break;
+ case 'w':
+ n_writers = ACE_OS::atoi (get_opt.opt_arg ());
+ break;
+ case 'n':
+ n_iterations = ACE_OS::atoi (get_opt.opt_arg ());
+ break;
+ case 'l':
+ n_loops = ACE_OS::atoi (get_opt.opt_arg ());
+ break;
+ default:
+ print_usage_and_die ();
+ break;
+ }
+}
+
+// Iterate <n_iterations> each time checking that nobody modifies the
+// data while we have a read lock.
+
+static void *
+reader (void *)
+{
+ ACE_DEBUG ((LM_DEBUG, "(%t) reader starting\n"));
+
+ for (int iterations = 1;
+ iterations <= n_iterations; iterations++)
+ {
+ ACE_Read_Guard<ACE_RW_Mutex> g(rw_mutex);
+
+ ++current_readers;
+
+ if (current_writers > 0)
+ ACE_DEBUG ((LM_DEBUG, "(%t) writers found!!!\n"));
+
+ ACE_thread_t thr_id = shared_thr_id;
+
+ for (int loop = 1; loop <= n_loops; loop++)
+ {
+ ACE_Thread::yield();
+
+ if (ACE_OS::thr_equal (shared_thr_id, thr_id) == 0)
+ ACE_DEBUG ((LM_DEBUG,
+ "(%t) somebody changed %d to %d\n",
+ thr_id, shared_thr_id));
+ }
+
+ --current_readers;
+
+ ACE_Thread::yield ();
+ }
+ return 0;
+}
+
+// Iterate <n_iterations> each time modifying the global data
+// and checking that nobody steps on it while we can write it.
+
+static void *
+writer (void *)
+{
+ ACE_DEBUG ((LM_DEBUG, "(%t) writer starting\n"));
+
+ for (int iterations = 1;
+ iterations <= n_iterations;
+ iterations++)
+ {
+ ACE_Write_Guard<ACE_RW_Mutex> g(rw_mutex);
+
+ ++current_writers;
+
+ if (current_writers > 1)
+ ACE_DEBUG ((LM_DEBUG, "(%t) other writers found!!!\n"));
+
+ if (current_readers > 0)
+ ACE_DEBUG ((LM_DEBUG, "(%t) readers found!!!\n"));
+
+ ACE_thread_t self = ACE_Thread::self ();
+ shared_thr_id = self;
+
+ for (int loop = 1; loop <= n_loops; loop++)
+ {
+ ACE_Thread::yield();
+
+ if (ACE_OS::thr_equal (shared_thr_id, self) == 0)
+ ACE_DEBUG ((LM_DEBUG, "(%t) somebody wrote on my data %d\n",
+ shared_thr_id));
+ }
+
+ --current_writers;
+
+ ACE_Thread::yield ();
+ }
+ return 0;
+}
+
+// Spawn off threads.
+
+int ACE_TMAIN (int argc, ACE_TCHAR *argv[])
+{
+ ACE_LOG_MSG->open (argv[0]);
+ parse_args (argc, argv);
+
+ current_readers = 0; // Possibly already done
+ current_writers = 0; // Possibly already done
+
+ ACE_DEBUG ((LM_DEBUG, "(%t) main thread starting\n"));
+
+ if (thr_mgr.spawn_n (n_readers, (ACE_THR_FUNC) reader, 0, THR_NEW_LWP) == -1 ||
+ thr_mgr.spawn_n (n_writers, (ACE_THR_FUNC) writer, 0, THR_NEW_LWP) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "spawn_n"), 1);
+
+ thr_mgr.wait ();
+
+ ACE_DEBUG ((LM_DEBUG, "(%t) exiting main thread\n"));
+ return 0;
+}
+
+#else
+int
+ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ ACE_ERROR ((LM_ERROR, "threads not supported on this platform\n"));
+ return 0;
+}
+#endif /* ACE_HAS_THREADS */
diff --git a/ACE/examples/Threads/recursive_mutex.cpp b/ACE/examples/Threads/recursive_mutex.cpp
new file mode 100644
index 00000000000..3c915682d90
--- /dev/null
+++ b/ACE/examples/Threads/recursive_mutex.cpp
@@ -0,0 +1,113 @@
+// $Id$
+
+// This test program verifies the functionality of the ACE_OS
+// implementation of recursive mutexes on Win32 and Posix pthreads.
+
+#include "ace/OS_main.h"
+#include "ace/Service_Config.h"
+#include "ace/Thread_Manager.h"
+#include "ace/Get_Opt.h"
+
+ACE_RCSID(Threads, recursive_mutex, "$Id$")
+
+#if defined (ACE_HAS_THREADS)
+
+#include "ace/Guard_T.h"
+#include "ace/Recursive_Thread_Mutex.h"
+
+// Total number of iterations.
+static size_t n_iterations = 1000;
+static size_t n_threads = 4;
+
+// Explain usage and exit.
+static void
+print_usage_and_die (void)
+{
+ ACE_DEBUG ((LM_DEBUG,
+ "usage: %n [-t n_threads] [-n iteration_count]\n"));
+ ACE_OS::exit (1);
+}
+
+// Parse the command-line arguments and set options.
+
+static void
+parse_args (int argc, ACE_TCHAR *argv[])
+{
+ ACE_Get_Opt get_opt (argc, argv, ACE_TEXT("n:t:"));
+
+ int c;
+
+ while ((c = get_opt ()) != -1)
+ switch (c)
+ {
+ case 'n':
+ n_iterations = ACE_OS::atoi (get_opt.opt_arg ());
+ break;
+ case 't':
+ n_threads = ACE_OS::atoi (get_opt.opt_arg ());
+ break;
+ default:
+ print_usage_and_die ();
+ break;
+ }
+}
+
+static void
+recursive_worker (size_t nesting_level,
+ ACE_Recursive_Thread_Mutex *rm)
+{
+ if (nesting_level < n_iterations)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ "(%P|%t) = trying to acquire, nesting = %d, thread id = %u\n",
+ rm->get_nesting_level (), rm->get_thread_id ()));
+ {
+ // This illustrates the use of the ACE_Guard<LOCK> with an
+ // ACE_Recursive_Thread_Mutex.
+ ACE_GUARD (ACE_Recursive_Thread_Mutex, ace_mon, *rm);
+ ACE_DEBUG ((LM_DEBUG,
+ "(%P|%t) = acquired, nesting = %d, thread id = %u\n",
+ rm->get_nesting_level (), rm->get_thread_id ()));
+
+ recursive_worker (nesting_level + 1, rm);
+ }
+ ACE_DEBUG ((LM_DEBUG,
+ "(%P|%t) = released, nesting = %d, thread id = %u\n",
+ rm->get_nesting_level (), rm->get_thread_id ()));
+ }
+}
+
+static void *
+worker (void *arg)
+{
+ ACE_Recursive_Thread_Mutex *rm
+ = (ACE_Recursive_Thread_Mutex *) arg;
+
+ recursive_worker (0, rm);
+ return 0;
+}
+
+int
+ACE_TMAIN (int argc, ACE_TCHAR *argv[])
+{
+ ACE_Service_Config daemon (argv[0]);
+
+ parse_args (argc, argv);
+ ACE_Recursive_Thread_Mutex rm;
+
+ ACE_Thread_Manager::instance ()->spawn_n (n_threads,
+ ACE_THR_FUNC (worker),
+ (void *) &rm);
+
+ ACE_Thread_Manager::instance ()->wait ();
+ return 0;
+}
+#else
+int
+ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "ACE doesn't support support process mutexes on this platform (yet)\n"),
+ -1);
+}
+#endif /* ACE_WIN32 */
diff --git a/ACE/examples/Threads/task_five.cpp b/ACE/examples/Threads/task_five.cpp
new file mode 100644
index 00000000000..8f96ee3420e
--- /dev/null
+++ b/ACE/examples/Threads/task_five.cpp
@@ -0,0 +1,177 @@
+// $Id$
+
+// ============================================================================
+//
+// = LIBRARY
+// examples/Threads/
+//
+// = FILENAME
+// task_five.cpp
+//
+// = DESCRIPTION
+// Stress testing thread creation and thread cancellation using
+// ACE_Task.
+//
+// = AUTHOR
+// Author: Detlef Becker <Detlef.Becker@med.siemens.de>
+//
+// ============================================================================
+
+
+#include "ace/OS_main.h"
+#include "ace/Thread_Manager.h"
+#include "ace/Task.h"
+#include "ace/OS_NS_unistd.h"
+
+ACE_RCSID(Threads, task_five, "$Id$")
+
+static const int DEFAULT_TASKS = 100;
+static const int DEFAULT_ITERATIONS = 10;
+
+// Default stack size
+static size_t default_stack_size =
+#if defined (ACE_WIN32)
+ 0;
+#else
+ 8192;
+#endif /* ACE_WIN32 */
+ u_int loop_count = 0;
+ u_int error_count = 0;
+
+class Test_Task : public ACE_Task<ACE_SYNCH>
+{
+public:
+ Test_Task (ACE_Thread_Manager * = ACE_Thread_Manager::instance ());
+ ~Test_Task (void) {};
+
+ int open (void * = 0);
+ int svc (void);
+ int close (u_long);
+ int shutdown (void);
+ int synch (void);
+};
+
+Test_Task::Test_Task (ACE_Thread_Manager *thrmgr)
+ : ACE_Task<ACE_SYNCH> (thrmgr)
+{
+}
+
+int
+Test_Task::open (void *)
+{
+ return this->activate (0,
+ 1,
+ 0,
+ ACE_DEFAULT_THREAD_PRIORITY,
+ -1,
+ 0,
+ 0,
+ 0,
+ &default_stack_size);
+}
+
+int
+Test_Task::svc (void)
+{
+ while (thr_mgr_->testcancel (ACE_OS::thr_self ()) == 0)
+ // Sleep for 350 msecs.
+ ACE_OS::sleep (ACE_Time_Value (0, 350000));
+
+ return 0;
+}
+
+int
+Test_Task::close (u_long)
+{
+ ACE_DEBUG ((LM_DEBUG, "(%t) closing down\n"));
+ return 0;
+}
+
+int
+Test_Task::shutdown (void)
+{
+ return thr_mgr_->cancel_grp (grp_id_);
+}
+
+int
+Test_Task::synch (void)
+{
+ return thr_mgr_->wait_grp (grp_id_);
+}
+
+static void
+work (ACE_Thread_Manager *thr_mgr,
+ int n_tasks,
+ size_t stack_size)
+{
+ ACE_UNUSED_ARG (stack_size);
+
+ int i;
+ Test_Task *task_array;
+
+ ACE_NEW (task_array,
+ Test_Task[n_tasks]);
+
+ ACE_DEBUG ((LM_DEBUG,
+ "Opening Tasks, loop count = %d, error count = %d\n",
+ loop_count,
+ error_count));
+
+ for (i = 0;
+ i < n_tasks;
+ i++)
+ task_array[i].open ();
+
+ ACE_OS::sleep (1);
+
+ ACE_DEBUG ((LM_DEBUG,
+ "Cancelling Tasks, loop count = %d, error count = %d\n",
+ loop_count,
+ error_count));
+
+ for (i = 0; i < n_tasks; i++)
+ task_array[i].shutdown ();
+
+ ACE_DEBUG ((LM_DEBUG,
+ "Synching Tasks, loop count = %d, error count = %d\n",
+ loop_count,
+ error_count));
+
+ for (i = 0;
+
+ i < n_tasks; i++)
+ if (-1 == task_array[i].synch ())
+ {
+ ACE_ERROR ((LM_ERROR,
+ "Error in synch! loop count = %d, error count = %d\n",
+ loop_count,
+ error_count));
+ error_count++;
+ }
+
+ ACE_DEBUG ((LM_DEBUG,
+ "thr_mgr->wait ();! loop count = %d, error count = %d\n",
+ loop_count,
+ error_count));
+
+ // Wait for all the threads to finish.
+ thr_mgr->wait ();
+
+ delete [] task_array;
+ loop_count++;
+}
+
+int
+ACE_TMAIN (int argc, ACE_TCHAR *argv[])
+{
+ size_t stack_size = argc > 1 ? ACE_OS::atoi (argv[1]) : default_stack_size;
+ const int n_tasks = argc > 2 ? ACE_OS::atoi (argv[2]) : DEFAULT_TASKS;
+ u_int iterations = argc > 3 ? ACE_OS::atoi (argv[3]) : DEFAULT_ITERATIONS;
+
+ for (u_int i = 0; i < iterations; i++)
+ work (ACE_Thread_Manager::instance (),
+ n_tasks,
+ stack_size);
+
+ return 0;
+}
diff --git a/ACE/examples/Threads/task_four.cpp b/ACE/examples/Threads/task_four.cpp
new file mode 100644
index 00000000000..31610d56537
--- /dev/null
+++ b/ACE/examples/Threads/task_four.cpp
@@ -0,0 +1,307 @@
+// $Id$
+
+// The following test was written by Hamutal Yanay & Ari Erev's
+// (Ari_Erev@comverse.com).
+//
+// This test program test enhancements to the thread_manager and task
+// classes. The purpose of these enhancements was to allow the
+// thread_manager to recognize the concept of an ACE_Task and to be
+// able to group ACE_Tasks in groups.
+//
+// There are two main ACE_Tasks in this sample:
+//
+// Invoker_Task - is run from main (). It's purpose is to run a number of
+// ACE_Tasks of type Worker_Task. The number can be specified
+// on the command line.
+// After starting the tasks, the Invoker_Task groups all the tasks
+// in one group and then uses the
+// num_tasks_in_group () to find out if the real number of tasks
+// that are now running (should be the same as the number of tasks
+// started).
+// It also, suspends and resumes all the threads in the group to
+// test the suspend_grp () and resume_grp () methods.
+// Then it waits for all the tasks to end.
+//
+// Worker_Task - ACE_Tasks that are started by the Invoker_Task.
+// Each Worker_Task can start a number of threads.
+// The Worker_Task threads perform some work (iteration). The number
+// of the iterations can be specified on the command line.
+//
+// The command line syntax is:
+//
+// test_task [num_tasks] [num_threads] [num_iterations]
+
+#include "ace/OS_NS_unistd.h"
+#include "ace/OS_main.h"
+#include "ace/Task.h"
+#include "ace/Service_Config.h"
+
+ACE_RCSID(Threads, task_four, "$Id$")
+
+#if defined (ACE_HAS_THREADS)
+
+#include "ace/Task.h"
+
+class Invoker_Task : public ACE_Task<ACE_MT_SYNCH>
+{
+public:
+ Invoker_Task (ACE_Thread_Manager *thr_mgr,
+ size_t n_tasks,
+ size_t n_threads,
+ size_t n_iterations);
+ virtual int svc (void);
+ // creats <n_tasks> and wait for them to finish
+
+private:
+ size_t n_tasks_;
+ // Number of tasks to start.
+ size_t n_threads_;
+ // Number of threads per task.
+ size_t n_iterations_;
+ // Number of iterations per thread.
+};
+
+class Worker_Task : public ACE_Task<ACE_MT_SYNCH>
+{
+public:
+ Worker_Task (ACE_Thread_Manager *thr_mgr,
+ size_t n_threads,
+ size_t n_iterations);
+ virtual int svc (void);
+ // Does a small work...
+ virtual int open (void * = NULL);
+
+private:
+ static size_t workers_count_;
+ size_t index_;
+ size_t n_threads_;
+ size_t n_iterations_;
+
+ // = Not needed for this test.
+ virtual int close (u_long);
+ virtual int put (ACE_Message_Block *, ACE_Time_Value *) { return 0; }
+};
+
+size_t Worker_Task::workers_count_ = 1;
+
+int
+Worker_Task::close (u_long)
+{
+ ACE_DEBUG ((LM_DEBUG,
+ "(%t) closing task %d\n",
+ this->index_));
+ delete this;
+ return 0;
+}
+
+Worker_Task::Worker_Task (ACE_Thread_Manager *thr_mgr,
+ size_t n_threads,
+ size_t n_iterations)
+ : ACE_Task<ACE_MT_SYNCH> (thr_mgr),
+ index_ (Worker_Task::workers_count_++),
+ n_threads_ (n_threads),
+ n_iterations_ (n_iterations)
+{
+}
+
+int
+Worker_Task::open (void *)
+{
+ // Create the pool of worker threads.
+ return this->activate (THR_NEW_LWP,
+ n_threads_,
+ 0,
+ -1,
+ -1,
+ this);
+}
+
+int
+Worker_Task::svc (void)
+{
+ ACE_DEBUG ((LM_DEBUG,
+ " (%t) in worker %d\n",
+ index_));
+
+ for (size_t iterations = 1;
+ iterations <= this->n_iterations_;
+ iterations++)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ " (%t) in iteration %d\n",
+ iterations));
+ ACE_OS::sleep (0);
+ }
+
+ ACE_DEBUG ((LM_DEBUG,
+ " (%t) worker %d ends\n",
+ index_));
+
+ return 0;
+}
+
+Invoker_Task::Invoker_Task (ACE_Thread_Manager *thr_mgr,
+ size_t n_tasks,
+ size_t n_threads,
+ size_t n_iterations)
+ : ACE_Task<ACE_MT_SYNCH> (thr_mgr),
+ n_tasks_ (n_tasks),
+ n_threads_ (n_threads),
+ n_iterations_ (n_iterations)
+{
+ // Create a single worker thread.
+ if (this->activate (THR_NEW_LWP,
+ 1,
+ 0,
+ -1,
+ -1,
+ this) == -1)
+ ACE_ERROR ((LM_ERROR,
+ "%p\n",
+ "activate failed"));
+}
+
+// Iterate <n_iterations> time printing off a message and "waiting"
+// for all other threads to complete this iteration.
+
+int
+Invoker_Task::svc (void)
+{
+ // Note that the ACE_Task::svc_run () method automatically adds us
+ // to the Thread_Manager when the thread begins.
+
+ ACE_Thread_Manager *thr_mgr =
+ ACE_Thread_Manager::instance ();
+ Worker_Task **worker_task = 0;
+
+ ACE_NEW_RETURN (worker_task,
+ Worker_Task *[n_tasks_],
+ -1);
+ size_t task = 0;
+
+ for (task = 0;
+ task < this->n_tasks_;
+ task++)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ " (%t) in task %d\n",
+ task + 1));
+
+ ACE_NEW_RETURN (worker_task[task],
+ Worker_Task (thr_mgr,
+ n_threads_,
+ n_iterations_),
+ -1);
+
+ if (worker_task[task]->open () == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%p\n",
+ "open failed"),
+ -1);
+ }
+
+ // Set all tasks to be one group
+ ACE_DEBUG ((LM_DEBUG,
+ " (%t) setting tasks group id\n"));
+
+ for (task = 0;
+ task < this->n_tasks_;
+ task++)
+ if (thr_mgr->set_grp (worker_task[task],
+ 1) == -1)
+ ACE_ERROR ((LM_DEBUG,
+ " (%t) %p\n",
+ "set_grp"));
+
+ size_t n_tasks =
+ thr_mgr->num_tasks_in_group (1);
+ ACE_DEBUG ((LM_DEBUG,
+ "Number of tasks in group 1: %d\n",
+ n_tasks)) ;
+
+ // Wait for 1 second and then suspend every thread in the group.
+ ACE_OS::sleep (1);
+ ACE_DEBUG ((LM_DEBUG,
+ " (%t) suspending group\n"));
+
+ if (thr_mgr->suspend_grp (1) == -1)
+ ACE_ERROR ((LM_DEBUG,
+ " (%t) %p\n",
+ "suspend_grp"));
+
+ // Wait for 3 more second and then resume every thread in the group.
+ ACE_OS::sleep (ACE_Time_Value (2));
+
+ ACE_DEBUG ((LM_DEBUG,
+ " (%t) resuming group\n"));
+
+ if (thr_mgr->resume_grp (1) == -1)
+ ACE_ERROR ((LM_DEBUG,
+ " (%t) %p\n",
+ "resume_grp"));
+
+ // Wait for all the tasks to reach their exit point.
+ thr_mgr->wait ();
+
+ // Note that the ACE_Task::svc_run () method automatically removes
+ // us from the Thread_Manager when the thread exits.
+ return 0;
+}
+
+// Default number of tasks and iterations.
+static const size_t DEFAULT_TASKS = 4;
+static const size_t DEFAULT_ITERATIONS = 5;
+
+int
+ACE_TMAIN (int argc, ACE_TCHAR *argv[])
+{
+ size_t n_tasks = argc > 1 ? ACE_OS::atoi (argv[1]) : DEFAULT_TASKS;
+ size_t n_threads = argc > 2 ? ACE_OS::atoi (argv[2]) : ACE_DEFAULT_THREADS;
+ size_t n_iterations = argc > 3 ? ACE_OS::atoi (argv[3]) : DEFAULT_ITERATIONS;
+
+ // Since ACE_Thread_Manager can only wait for all threads, we'll
+ // have special manager for the Invoker_Task.
+ ACE_Thread_Manager invoker_manager;
+
+ Invoker_Task invoker (&invoker_manager,
+ n_tasks,
+ n_threads,
+ n_iterations);
+
+ // Wait for 1 second and then suspend the invoker task
+ ACE_OS::sleep (1);
+ ACE_DEBUG ((LM_DEBUG,
+ " (%t) suspending invoker task\n"));
+
+ if (invoker_manager.suspend_task (&invoker) == -1)
+ ACE_ERROR ((LM_DEBUG,
+ " (%t) %p\n",
+ "suspend_task"));
+
+ // Wait for 3 more second and then resume the invoker task.
+ ACE_OS::sleep (ACE_Time_Value (3));
+
+ ACE_DEBUG ((LM_DEBUG,
+ " (%t) resuming invoker task\n"));
+
+ if (invoker_manager.resume_task (&invoker) == -1)
+ ACE_ERROR ((LM_DEBUG,
+ " (%t) %p\n",
+ "resume_task"));
+
+ // Wait for all the threads to reach their exit point.
+ invoker_manager.wait ();
+
+ ACE_DEBUG ((LM_DEBUG,
+ " (%t) done\n"));
+ return 0;
+}
+#else
+int
+ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ ACE_ERROR ((LM_ERROR,
+ "threads not supported on this platform\n"));
+ return 0;
+}
+#endif /* ACE_HAS_THREADS */
diff --git a/ACE/examples/Threads/task_one.cpp b/ACE/examples/Threads/task_one.cpp
new file mode 100644
index 00000000000..ea4fd71dcf8
--- /dev/null
+++ b/ACE/examples/Threads/task_one.cpp
@@ -0,0 +1,102 @@
+// $Id$
+
+// This test program illustrates how the ACE barrier synchronization
+// mechanisms work in conjunction with the ACE_Task and the
+// ACE_Thread_Manager. It is instructive to compare this with the
+// test_barrier.cpp test to see how they differ.
+
+#include "ace/OS_main.h"
+#include "ace/Task.h"
+#include "ace/Service_Config.h"
+
+ACE_RCSID(Threads, task_one, "$Id$")
+
+#if defined (ACE_HAS_THREADS)
+
+#include "ace/Task.h"
+#include "ace/Barrier.h"
+
+class Barrier_Task : public ACE_Task<ACE_MT_SYNCH>
+{
+public:
+ Barrier_Task (ACE_Thread_Manager *thr_mgr,
+ int n_threads,
+ int n_iterations);
+
+ virtual int svc (void);
+ // Iterate <n_iterations> time printing off a message and "waiting"
+ // for all other threads to complete this iteration.
+
+private:
+ ACE_Barrier barrier_;
+ // Reference to the tester barrier. This controls each
+ // iteration of the tester function running in every thread.
+
+ int n_iterations_;
+ // Number of iterations to run.
+};
+
+Barrier_Task::Barrier_Task (ACE_Thread_Manager *thr_mgr,
+ int n_threads,
+ int n_iterations)
+ : ACE_Task<ACE_MT_SYNCH> (thr_mgr),
+ barrier_ (n_threads),
+ n_iterations_ (n_iterations)
+{
+ // Create worker threads.
+ if (this->activate (THR_NEW_LWP, n_threads) == -1)
+ ACE_ERROR ((LM_ERROR, "%p\n", "activate failed"));
+}
+
+// Iterate <n_iterations> time printing off a message and "waiting"
+// for all other threads to complete this iteration.
+
+int
+Barrier_Task::svc (void)
+{
+ // Note that the ACE_Task::svc_run() method automatically adds us to
+ // the Thread_Manager when the thread begins.
+
+ for (int iterations = 1;
+ iterations <= this->n_iterations_;
+ iterations++)
+ {
+ ACE_DEBUG ((LM_DEBUG, "(%t) in iteration %d\n", iterations));
+
+ // Block until all other threads have waited, then continue.
+ this->barrier_.wait ();
+ }
+
+ // Note that the ACE_Task::svc_run() method automatically removes us
+ // from the Thread_Manager when the thread exits.
+
+ return 0;
+}
+
+// Default number of threads to spawn.
+static const int DEFAULT_ITERATIONS = 5;
+
+int
+ACE_TMAIN (int argc, ACE_TCHAR *argv[])
+{
+ int n_threads = argc > 1 ? ACE_OS::atoi (argv[1]) : ACE_DEFAULT_THREADS;
+ int n_iterations = argc > 2 ? ACE_OS::atoi (argv[2]) : DEFAULT_ITERATIONS;
+
+ Barrier_Task barrier_task (ACE_Thread_Manager::instance (),
+ n_threads,
+ n_iterations);
+
+ // Wait for all the threads to reach their exit point.
+ ACE_Thread_Manager::instance ()->wait ();
+
+ ACE_DEBUG ((LM_DEBUG, "(%t) done\n"));
+ return 0;
+}
+#else
+int
+main (int, char *[])
+{
+ ACE_ERROR ((LM_ERROR, "threads not supported on this platform\n"));
+ return 0;
+}
+#endif /* ACE_HAS_THREADS */
diff --git a/ACE/examples/Threads/task_three.cpp b/ACE/examples/Threads/task_three.cpp
new file mode 100644
index 00000000000..03f6e816572
--- /dev/null
+++ b/ACE/examples/Threads/task_three.cpp
@@ -0,0 +1,268 @@
+// $Id$
+
+// Exercise more tests for the <ACE_Task>s. This also shows off some
+// Interesting uses of the <ACE_Log_Msg>'s ability to print to
+// ostreams. BTW, make sure that you set the out_stream in *every*
+// thread that you want to have write to the output file, i.e.:
+//
+// if (out_stream)
+// {
+// ACE_LOG_MSG->set_flags (ACE_Log_Msg::OSTREAM);
+// ACE_LOG_MSG->msg_ostream (out_stream);
+// }
+
+#include "ace/OS_NS_unistd.h"
+#include "ace/OS_NS_stdio.h"
+#include "ace/OS_main.h"
+#include "ace/Reactor.h"
+#include "ace/Service_Config.h"
+#include "ace/Task.h"
+
+// FUZZ: disable check_for_streams_include
+#include "ace/streams.h"
+
+#include "ace/Signal.h"
+
+ACE_RCSID(Threads, task_three, "$Id$")
+
+#if defined (ACE_HAS_THREADS)
+
+static ACE_OSTREAM_TYPE *out_stream = 0;
+static sig_atomic_t done = 0;
+static const size_t NUM_INVOCATIONS = 100;
+static const size_t TASK_COUNT = 130;
+
+class Test_Task : public ACE_Task<ACE_MT_SYNCH>
+{
+public:
+ Test_Task (void);
+ ~Test_Task (void);
+
+ virtual int open (void *args = 0);
+ virtual int close (u_long flags = 0);
+ virtual int svc (void);
+
+ virtual int handle_input (ACE_HANDLE fd);
+
+ ACE_Reactor *r_;
+ size_t handled_;
+ static size_t current_count_;
+ static size_t done_cnt_;
+};
+
+size_t Test_Task::current_count_ = 0;
+size_t Test_Task::done_cnt_ = 0;
+
+static ACE_Thread_Mutex Lock;
+
+Test_Task::Test_Task (void)
+{
+ ACE_GUARD (ACE_Thread_Mutex, ace_mon, Lock);
+
+ this->handled_ = 0;
+ Test_Task::current_count_++;
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("Test_Task constructed, current_count_ = %d\n"),
+ Test_Task::current_count_));
+}
+
+Test_Task::~Test_Task (void)
+{
+ ACE_GUARD (ACE_Thread_Mutex, ace_mon, Lock);
+
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("Test_Task destroyed, current_count_ = %d\n"),
+ Test_Task::current_count_));
+}
+
+int
+Test_Task::open (void *args)
+{
+ r_ = reinterpret_cast <ACE_Reactor *> (args);
+ return ACE_Task<ACE_MT_SYNCH>::activate (THR_NEW_LWP);
+}
+
+int
+Test_Task::close (u_long)
+{
+ ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, Lock, -1);
+
+ Test_Task::current_count_--;
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("Test_Task::close () current_count_ = %d.\n"),
+ Test_Task::current_count_));
+ return 0;
+}
+
+int
+Test_Task::svc (void)
+{
+ // Every thread must register the same stream to write to file.
+ if (out_stream)
+ {
+ ACE_LOG_MSG->set_flags (ACE_Log_Msg::OSTREAM);
+ ACE_LOG_MSG->msg_ostream (out_stream);
+ }
+
+ for (size_t index = 0; index < NUM_INVOCATIONS; index++)
+ {
+ ACE_OS::thr_yield ();
+
+ if (r_->notify (this, ACE_Event_Handler::READ_MASK) == -1)
+ {
+ ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, Lock, -1);
+
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("Test_Task: error %p!\n"),
+ ACE_TEXT ("notifying reactor")),
+ 0);
+ }
+ }
+
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT (" (%t) returning from svc ()\n")));
+ return 0;
+}
+
+int
+Test_Task::handle_input (ACE_HANDLE)
+{
+ this->handled_++;
+
+ if (this->handled_ == NUM_INVOCATIONS)
+ {
+ ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, Lock, -1);
+ Test_Task::done_cnt_++;
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT (" (%t) Test_Task: handle_input done_cnt_ = %d.\n"),
+ Test_Task::done_cnt_));
+ }
+
+ ACE_OS::thr_yield ();
+ return -1;
+}
+
+static void *
+dispatch (void *arg)
+{
+ // every thread must register the same stream to write to file
+ if (out_stream)
+ {
+ ACE_LOG_MSG->set_flags (ACE_Log_Msg::OSTREAM);
+ ACE_LOG_MSG->msg_ostream (out_stream);
+ }
+
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT (" (%t) Dispatcher Thread started!\n")));
+ ACE_Reactor *r = reinterpret_cast <ACE_Reactor *> (arg);
+ int result;
+
+ r->owner (ACE_OS::thr_self ());
+
+ while (1)
+ {
+ result = r->handle_events ();
+
+ if (result <= 0)
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("Dispatch: handle_events (): %d"),
+ result));
+ }
+
+ ACE_NOTREACHED (return 0);
+}
+
+extern "C" void
+handler (int)
+{
+ done = 1;
+}
+
+int
+ACE_TMAIN (int argc, ACE_TCHAR **)
+{
+ if (argc > 1)
+ {
+ // Send output to file.
+#if !defined (ACE_LACKS_IOSTREAM_TOTALLY)
+ ACE_NEW_RETURN (out_stream,
+ ofstream ("test_task_three.out",
+ ios::trunc|ios::out),
+ -1);
+#else
+ if ((out_stream = ACE_OS::fopen ("test_task_three.out", "w")) == NULL)
+ return -1;
+#endif
+ ACE_LOG_MSG->set_flags (ACE_Log_Msg::OSTREAM);
+ ACE_LOG_MSG->msg_ostream (out_stream);
+ }
+
+ // Register a signal handler.
+ ACE_Sig_Action sa ((ACE_SignalHandler) handler, SIGINT);
+ ACE_UNUSED_ARG (sa);
+
+ ACE_Reactor *reactor1 = ACE_Reactor::instance ();
+ ACE_Reactor *reactor2 = new ACE_Reactor ();
+
+ Test_Task t1[TASK_COUNT];
+ Test_Task t2[TASK_COUNT];
+
+ ACE_Thread::spawn (ACE_THR_FUNC (dispatch),
+ reactor2);
+
+ reactor1->owner (ACE_OS::thr_self ());
+
+ for (size_t index = 0; index < TASK_COUNT; index++)
+ {
+ t1[index].open (reactor1);
+ t2[index].open (reactor2);
+ }
+
+ ACE_OS::sleep (3);
+
+ while (done == 0)
+ {
+ ACE_Time_Value timeout (2);
+
+ if (reactor1->handle_events (timeout) <= 0)
+ {
+ if (errno == ETIME)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("no activity within 2 seconds, shutting down\n")));
+ break;
+ }
+ else
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("%p error handling events\n"),
+ ACE_TEXT ("main")));
+ }
+ }
+
+ if (argc > 1)
+ {
+#if !defined (ACE_LACKS_IOSTREAM_TOTALLY)
+ *out_stream << flush;
+ delete out_stream;
+#else
+ ACE_OS::fflush(out_stream);
+ ACE_OS::fclose(out_stream);
+#endif
+ ACE_LOG_MSG->clr_flags (ACE_Log_Msg::OSTREAM);
+ ACE_LOG_MSG->msg_ostream (0);
+ }
+
+ // Bail out here so that we don't call the destructors for the tasks..
+ ACE_OS::exit (0);
+ /* NOTREACHED */
+
+ return 0;
+}
+
+#else
+int
+ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("threads not supported on this platform\n")));
+ return 0;
+}
+#endif /* ACE_HAS_THREADS */
diff --git a/ACE/examples/Threads/task_two.cpp b/ACE/examples/Threads/task_two.cpp
new file mode 100644
index 00000000000..7243ac5b1c3
--- /dev/null
+++ b/ACE/examples/Threads/task_two.cpp
@@ -0,0 +1,147 @@
+// $Id$
+
+// Exercise more tests for the ACE Tasks. This test can spawn off
+// zillions of tasks and then wait for them using both polling and the
+// ACE Thread Manager.
+
+#include "ace/OS_main.h"
+#include "ace/Task.h"
+
+#include "ace/Service_Config.h"
+#include "ace/Atomic_Op.h"
+
+ACE_RCSID(Threads, task_two, "$Id$")
+
+#if defined (ACE_HAS_THREADS)
+
+typedef ACE_Atomic_Op<ACE_Thread_Mutex, int> ATOMIC_INT;
+
+static int zero = 0;
+static ATOMIC_INT task_count (zero);
+static ATOMIC_INT max_count (zero);
+static ATOMIC_INT wait_count (zero);
+
+static int n_threads = 0;
+
+// Default number of tasks.
+static const int default_threads = ACE_DEFAULT_THREADS;
+
+// Default number of times to run the test.
+static const int default_iterations = 1000;
+
+class Task_Test : public ACE_Task<ACE_MT_SYNCH>
+{
+public:
+ virtual int open (void *args = 0);
+ virtual int close (u_long flags = 0);
+ virtual int svc (void);
+
+private:
+ static ACE_Thread_Mutex lock_;
+};
+
+ACE_Thread_Mutex Task_Test::lock_;
+
+int
+Task_Test::open (void *)
+{
+ ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, Task_Test::lock_, -1);
+
+ task_count++;
+ ACE_DEBUG ((LM_DEBUG, "(%t) creating Task_Test, task count = %d\n",
+ task_count.value ()));
+
+ return this->activate (THR_BOUND);
+}
+
+int
+Task_Test::close (u_long)
+{
+ ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, Task_Test::lock_, -1);
+
+ task_count--;
+ ACE_DEBUG ((LM_DEBUG, "(%t) destroying Task_Test, task count = %d\n",
+ task_count.value ()));
+ wait_count--;
+ return 0;
+}
+
+int
+Task_Test::svc (void)
+{
+ wait_count++;
+ max_count++;
+
+ ACE_DEBUG ((LM_DEBUG, "(%t) svc: waiting\n"));
+
+ for (;;)
+ if (max_count >= n_threads)
+ break;
+ else
+ ACE_Thread::yield ();
+
+ ACE_DEBUG ((LM_DEBUG, "(%t) svc: finished waiting\n"));
+ return 0;
+}
+
+int
+ACE_TMAIN (int argc, ACE_TCHAR *argv[])
+{
+ n_threads = argc > 1 ? ACE_OS::atoi (argv[1]) : default_threads;
+ int n_iterations = argc > 2 ? ACE_OS::atoi (argv[2]) : default_iterations;
+
+ Task_Test **task_array = new Task_Test *[n_threads];
+
+ for (int i = 1; i <= n_iterations; i++)
+ {
+ ACE_DEBUG ((LM_DEBUG, "(%t) iteration = %d, max_count %d\n",
+ i, max_count.value ()));
+ max_count = 0;
+
+ ACE_DEBUG ((LM_DEBUG, "(%t) starting %d task%s\n",
+ n_threads, n_threads == 1 ? "" : "s"));
+
+ // Launch the new tasks.
+ for (int j = 0; j < n_threads; j++)
+ {
+ task_array[j] = new Task_Test;
+ // Activate the task, i.e., make it an active object.
+ task_array[j]->open ();
+ }
+
+ // Wait for initialization to kick in.
+ while (max_count == 0)
+ ACE_Thread::yield ();
+
+ ACE_DEBUG ((LM_DEBUG, "(%t) waiting for threads to finish\n"));
+
+ // Wait for the threads to finish this iteration.
+ while (max_count != n_threads && wait_count != 0)
+ ACE_Thread::yield ();
+
+ ACE_DEBUG ((LM_DEBUG,
+ "(%t) iteration %d finished, max_count %d, wait_count %d, waiting for tasks to exit\n",
+ i, max_count.value (), wait_count.value ()));
+
+ // Wait for all the tasks to exit.
+ ACE_Thread_Manager::instance ()->wait ();
+
+ // Delete the existing tasks.
+ for (int k = 0; k < n_threads; k++)
+ delete task_array[k];
+ }
+
+ delete [] task_array;
+
+ ACE_DEBUG ((LM_DEBUG, "(%t) shutting down the test\n"));
+ return 0;
+}
+
+#else
+int
+ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ ACE_ERROR ((LM_ERROR, "threads not supported on this platform\n"));
+ return 0;
+}
+#endif /* ACE_HAS_THREADS */
diff --git a/ACE/examples/Threads/thread_manager.cpp b/ACE/examples/Threads/thread_manager.cpp
new file mode 100644
index 00000000000..e6f12f6c939
--- /dev/null
+++ b/ACE/examples/Threads/thread_manager.cpp
@@ -0,0 +1,108 @@
+// $Id$
+
+// Test out the group management mechanisms provided by the
+// ACE_Thread_Manager, including the group signal handling, group
+// suspension and resumption, and cooperative thread cancellation
+// mechanisms.
+
+#include "ace/OS_NS_unistd.h"
+#include "ace/OS_main.h"
+#include "ace/Service_Config.h"
+#include "ace/Thread_Manager.h"
+#include "ace/Signal.h"
+
+ACE_RCSID(Threads, thread_manager, "$Id$")
+
+#if defined (ACE_HAS_THREADS)
+
+extern "C" void
+handler (int signum)
+{
+ ACE_DEBUG ((LM_DEBUG, "(%t) received signal %d\n", signum));
+}
+
+static void *
+worker (int iterations)
+{
+ for (int i = 0; i < iterations; i++)
+ {
+ if ((i % 1000) == 0)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ "(%t) checking cancellation before iteration %d!\n",
+ i));
+
+ if (ACE_Thread_Manager::instance ()->testcancel (ACE_Thread::self ()) != 0)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ "(%t) has been cancelled before iteration %d!\n",
+ i));
+ break;
+ }
+ }
+ }
+
+ // Destructor removes thread from Thread_Manager.
+ return 0;
+}
+
+static const int DEFAULT_THREADS = ACE_DEFAULT_THREADS;
+static const int DEFAULT_ITERATIONS = 100000;
+
+int
+ACE_TMAIN (int argc, ACE_TCHAR *argv[])
+{
+ ACE_Service_Config daemon;
+
+ daemon.open (argv[0]);
+
+ // Register a signal handler.
+ ACE_Sig_Action sa ((ACE_SignalHandler) handler, SIGINT);
+ ACE_UNUSED_ARG (sa);
+
+ int n_threads = argc > 1 ? ACE_OS::atoi (argv[1]) : DEFAULT_THREADS;
+ int n_iterations = argc > 2 ? ACE_OS::atoi (argv[2]) : DEFAULT_ITERATIONS;
+
+ ACE_Thread_Manager *thr_mgr = ACE_Thread_Manager::instance ();
+
+ int grp_id = thr_mgr->spawn_n (n_threads, ACE_THR_FUNC (worker),
+ reinterpret_cast<void *> (n_iterations),
+ THR_NEW_LWP | THR_DETACHED);
+
+ // Wait for 1 second and then suspend every thread in the group.
+ ACE_OS::sleep (1);
+ ACE_DEBUG ((LM_DEBUG, "(%t) suspending group\n"));
+ if (thr_mgr->suspend_grp (grp_id) == -1)
+ ACE_ERROR ((LM_DEBUG, "(%t) %p\n", "suspend_grp"));
+
+ // Wait for 1 more second and then resume every thread in the
+ // group.
+ ACE_OS::sleep (ACE_Time_Value (1));
+ ACE_DEBUG ((LM_DEBUG, "(%t) resuming group\n"));
+ if (thr_mgr->resume_grp (grp_id) == -1)
+ ACE_ERROR ((LM_DEBUG, "(%t) %p\n", "resume_grp"));
+
+ // Wait for 1 more second and then send a SIGINT to every thread in
+ // the group.
+ ACE_OS::sleep (ACE_Time_Value (1));
+ ACE_DEBUG ((LM_DEBUG, "(%t) signaling group\n"));
+ if (thr_mgr->kill_grp (grp_id, SIGINT) == -1)
+ ACE_ERROR ((LM_DEBUG, "(%t) %p\n", "kill_grp"));
+
+ // Wait for 1 more second and then cancel all the threads.
+ ACE_OS::sleep (ACE_Time_Value (1));
+ ACE_DEBUG ((LM_DEBUG, "(%t) cancelling group\n"));
+ if (thr_mgr->cancel_grp (grp_id) == -1)
+ ACE_ERROR ((LM_DEBUG, "(%t) %p\n", "cancel_grp"));
+
+ // Perform a barrier wait until all the threads have shut down.
+ thr_mgr->wait ();
+ return 0;
+}
+#else
+int
+ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ ACE_ERROR_RETURN ((LM_ERROR, "threads not supported on this platform\n"), -1);
+}
+#endif /* ACE_HAS_THREADS */
diff --git a/ACE/examples/Threads/thread_pool.cpp b/ACE/examples/Threads/thread_pool.cpp
new file mode 100644
index 00000000000..cab0699f428
--- /dev/null
+++ b/ACE/examples/Threads/thread_pool.cpp
@@ -0,0 +1,268 @@
+// $Id$
+
+// This test program illustrates how the <ACE_Task> synchronization
+// mechanisms work in conjunction with the <ACE_Thread_Manager>. If
+// the <manual> flag is set input comes from stdin until the user
+// enters a return -- otherwise, the input is generated automatically.
+// All worker threads shutdown when they receive a message block of
+// length 0.
+//
+// This code is original based on a test program written by Karlheinz
+// Dorn <Karlheinz.Dorn@med.siemens.de>. It was modified to utilize
+// more ACE features by Doug Schmidt <schmidt@cs.wustl.edu>.
+
+#include "ace/OS_NS_stdio.h"
+#include "ace/OS_NS_string.h"
+#include "ace/OS_NS_unistd.h"
+#include "ace/OS_main.h"
+#include "ace/Task.h"
+#include "ace/Service_Config.h"
+
+ACE_RCSID(Threads, thread_pool, "$Id$")
+
+#if defined (ACE_HAS_THREADS)
+
+// Default number of iterations to run the test.
+static int n_iterations = 100;
+
+// Controls whether the input is generated "manually" or automatically.
+static int manual = 0;
+
+class Thread_Pool : public ACE_Task<ACE_MT_SYNCH>
+{
+ // = TITLE
+ // Defines a thread pool abstraction based on the <ACE_Task>.
+public:
+ Thread_Pool (ACE_Thread_Manager *thr_mgr,
+ int n_threads);
+ // Constructor activates <n_threads> in the thread pool.
+
+ ~Thread_Pool (void);
+ // Destructor...
+
+ virtual int svc (void);
+ // Iterate <n_iterations> time printing off a message and "waiting"
+ // for all other threads to complete this iteration.
+
+ virtual int put (ACE_Message_Block *mb,
+ ACE_Time_Value *tv = 0);
+ // This allows the producer to pass messages to the <Thread_Pool>.
+
+private:
+ virtual int close (u_long);
+ // Close hook.
+};
+
+int
+Thread_Pool::close (u_long)
+{
+ ACE_DEBUG ((LM_DEBUG,
+ "(%t) worker thread closing down\n"));
+ return 0;
+}
+
+Thread_Pool::Thread_Pool (ACE_Thread_Manager *thr_mgr,
+ int n_threads)
+ : ACE_Task<ACE_MT_SYNCH> (thr_mgr)
+{
+ // Create the pool of worker threads.
+ if (this->activate (THR_NEW_LWP,
+ n_threads) == -1)
+ ACE_ERROR ((LM_ERROR,
+ "%p\n",
+ "activate failed"));
+}
+
+Thread_Pool::~Thread_Pool (void)
+{
+}
+
+// Simply enqueue the Message_Block into the end of the queue.
+
+int
+Thread_Pool::put (ACE_Message_Block *mb,
+ ACE_Time_Value *tv)
+{
+ return this->putq (mb, tv);
+}
+
+// Iterate <n_iterations> time printing off a message and "waiting"
+// for all other threads to complete this iteration.
+
+int
+Thread_Pool::svc (void)
+{
+ // Note that the <ACE_Task::svc_run> method automatically adds us to
+ // the Thread_Manager when the thread begins.
+
+ int count = 1;
+
+ // Keep looping, reading a message out of the queue, until we get a
+ // message with a length == 0, which signals us to quit.
+
+ for (;; count++)
+ {
+ ACE_Message_Block *mb;
+
+ ACE_DEBUG ((LM_DEBUG,
+ "(%t) in iteration %d before getq ()\n",
+ count));
+
+ if (this->getq (mb) == -1)
+ {
+ ACE_ERROR ((LM_ERROR,
+ "(%t) in iteration %d, got result -1, exiting\n",
+ count));
+ break;
+ }
+
+ size_t length = mb->length ();
+
+ if (length > 0)
+ ACE_DEBUG ((LM_DEBUG,
+ "(%t) in iteration %d, length = %d, text = \"%*s\"\n",
+ count,
+ length,
+ length - 1,
+ mb->rd_ptr ()));
+
+ // We're responsible for deallocating this.
+ mb->release ();
+
+ if (length == 0)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ "(%t) in iteration %d, got NULL message, exiting\n",
+ count));
+ break;
+ }
+ }
+
+ // Note that the <ACE_Task::svc_run> method automatically removes us
+ // from the <ACE_Thread_Manager> when the thread exits.
+ return 0;
+}
+
+static void
+producer (Thread_Pool &thread_pool)
+{
+ ACE_DEBUG ((LM_DEBUG,
+ "(%t) producer start, generating data for the <Thread_Pool>\n"));
+ // thread_pool.dump ();
+
+ for (int n; ;)
+ {
+ // Allocate a new message.
+ ACE_Message_Block *mb = 0;
+ ACE_NEW (mb,
+ ACE_Message_Block (BUFSIZ));
+
+ if (manual)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ "(%t) enter a new message for the task pool..."));
+ n = ACE_OS::read (ACE_STDIN,
+ mb->rd_ptr (),
+ mb->size ());
+ }
+ else
+ {
+ static int count = 0;
+
+ ACE_OS::sprintf (mb->rd_ptr (),
+ "%d\n",
+ count);
+ n = ACE_OS::strlen (mb->rd_ptr ());
+
+ if (count == n_iterations)
+ n = 1; // Indicate that we need to shut down.
+ else
+ count++;
+
+ if (count == 0 || (count % 20 == 0))
+ ACE_OS::sleep (1);
+ }
+
+ if (n > 1)
+ {
+ // Send a normal message to the waiting threads and continue
+ // producing.
+ mb->wr_ptr (n);
+
+ // Pass the message to the Thread_Pool.
+ if (thread_pool.put (mb) == -1)
+ ACE_ERROR ((LM_ERROR,
+ " (%t) %p\n",
+ "put"));
+ }
+ else
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ "\n(%t) start loop, dump of task:\n"));
+ // thread_pool.dump ();
+
+ // Send a shutdown message to the waiting threads and exit.
+ for (size_t i = thread_pool.thr_count (); i > 0; i--)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ "(%t) EOF, enqueueing NULL block for thread = %d\n",
+ i));
+
+ // Enqueue a NULL message to flag each consumer to
+ // shutdown.
+ ACE_Message_Block *mb = 0;
+ ACE_NEW (mb,
+ ACE_Message_Block);
+ if (thread_pool.put (mb) == -1)
+ ACE_ERROR ((LM_ERROR,
+ " (%t) %p\n",
+ "put"));
+ }
+
+ ACE_DEBUG ((LM_DEBUG,
+ "\n(%t) end loop\n"));
+ // thread_pool.dump ();
+ break;
+ }
+ }
+}
+
+int
+ACE_TMAIN (int argc, ACE_TCHAR *argv[])
+{
+ int n_threads = argc > 1 ? ACE_OS::atoi (argv[1]) : ACE_DEFAULT_THREADS;
+ n_iterations = argc > 2 ? ACE_OS::atoi (argv[2]) : n_iterations;
+ manual = argc > 3 ? 1 : 0;
+
+ ACE_DEBUG ((LM_DEBUG,
+ "(%t) argc = %d, threads = %d\n",
+ argc,
+ n_threads));
+
+ // Create the worker tasks.
+ Thread_Pool thread_pool (ACE_Thread_Manager::instance (),
+ n_threads);
+
+ // Create work for the worker tasks to process in their own threads.
+ producer (thread_pool);
+
+ ACE_DEBUG ((LM_DEBUG,
+ "(%t) waiting for threads to exit in Thread_Pool destructor...\n"));
+ // Wait for all the threads to reach their exit point.
+ if (thread_pool.wait () == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, "(%t) wait() failed\n"),
+ 1);
+
+ ACE_DEBUG ((LM_DEBUG,
+ "(%t) destroying worker tasks and exiting...\n"));
+ return 0;
+}
+#else
+int
+ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ ACE_ERROR ((LM_ERROR,
+ "threads not supported on this platform\n"));
+ return 0;
+}
+#endif /* ACE_HAS_THREADS */
diff --git a/ACE/examples/Threads/thread_specific.cpp b/ACE/examples/Threads/thread_specific.cpp
new file mode 100644
index 00000000000..04cb3d94627
--- /dev/null
+++ b/ACE/examples/Threads/thread_specific.cpp
@@ -0,0 +1,228 @@
+// $Id$
+
+#include "ace/OS_NS_stdio.h"
+#include "ace/OS_NS_unistd.h"
+#include "ace/OS_main.h"
+#include "ace/Service_Config.h"
+#include "ace/Thread_Manager.h"
+#include "ace/Signal.h"
+
+ACE_RCSID(Threads, thread_specific, "$Id$")
+
+#if defined (ACE_HAS_THREADS)
+
+#include "thread_specific.h"
+
+// Static variables.
+ACE_MT (ACE_Thread_Mutex Errno::lock_);
+int Errno::flags_;
+
+// This is our thread-specific error handler...
+static ACE_TSS<Errno> tss_error;
+
+// Serializes output via cout.
+static ACE_SYNCH_MUTEX printf_lock;
+
+#if defined (ACE_HAS_THREADS)
+typedef ACE_TSS_Guard<ACE_Thread_Mutex> GUARD;
+#else
+typedef ACE_Guard<ACE_Null_Mutex> GUARD;
+#endif /* ACE_HAS_THREADS */
+
+extern "C" void
+cleanup (void *ptr)
+{
+ ACE_DEBUG ((LM_DEBUG,
+ "(%t) in cleanup, ptr = %x\n",
+ ptr));
+
+ delete reinterpret_cast<char *> (ptr);
+}
+
+// This worker function is the entry point for each thread.
+
+static void *
+worker (void *c)
+{
+ // Cast the arg to a long, first, because a pointer is the same size
+ // as a long on all current ACE platforms.
+ int count = (int) (long) c;
+
+ ACE_thread_key_t key = ACE_OS::NULL_key;
+ int *ip = 0;
+
+ // Make one key that will be available when the thread exits so that
+ // we'll have something to cleanup!
+
+ if (ACE_Thread::keycreate (&key, cleanup) == -1)
+ ACE_ERROR ((LM_ERROR,
+ "(%t) %p\n",
+ "ACE_Thread::keycreate"));
+
+ ACE_NEW_RETURN (ip,
+ int,
+ 0);
+
+ if (ACE_Thread::setspecific (key, (void *) ip) == -1)
+ ACE_ERROR ((LM_ERROR,
+ "(%t) %p\n",
+ "ACE_Thread::setspecific"));
+
+ for (int i = 0; i < count; i++)
+ {
+ if (ACE_Thread::keycreate (&key, cleanup) == -1)
+ ACE_ERROR ((LM_ERROR,
+ "(%t) %p\n",
+ "ACE_Thread::keycreate"));
+
+ ACE_NEW_RETURN (ip,
+ int,
+ 0);
+
+ ACE_DEBUG ((LM_DEBUG,
+ "(%t) in worker 1, key = %d, ip = %x\n",
+ key,
+ ip));
+
+ if (ACE_Thread::setspecific (key, (void *) ip) == -1)
+ ACE_ERROR ((LM_ERROR,
+ "(%t) %p\n",
+ "ACE_Thread::setspecific"));
+
+ if (ACE_Thread::getspecific (key, (void **) &ip) == -1)
+ ACE_ERROR ((LM_ERROR,
+ "(%t) %p\n",
+ "ACE_Thread::setspecific"));
+
+ if (ACE_Thread::setspecific (key, (void *) 0) == -1)
+ ACE_ERROR ((LM_ERROR,
+ "(%t) %p\n",
+ "ACE_Thread::setspecific"));
+ delete ip;
+
+ if (ACE_Thread::keyfree (key) == -1)
+ ACE_ERROR ((LM_ERROR,
+ "(%t) %p\n",
+ "ACE_Thread::keyfree"));
+
+ // Cause an error.
+ ACE_OS::read (ACE_INVALID_HANDLE, 0, 0);
+
+ // The following two lines set the thread-specific state.
+ tss_error->error (errno);
+ tss_error->line (__LINE__);
+
+ // This sets the static state (note how C++ makes it easy to do
+ // both).
+ tss_error->flags (count);
+
+ {
+ ACE_hthread_t handle;
+ ACE_Thread::self (handle);
+
+ // Use the guard to serialize access to printf...
+ ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, printf_lock, 0);
+
+#if defined(linux) || defined(__OpenBSD__)
+ // @@ Normally the platform specific way to print a thread ID
+ // is encapsulated in Log_Msg.cpp, but for this small example
+ // we cannot (or do not want to) use ACE_Log_Msg.
+ ACE_OS::printf ("(%lu)", (unsigned long)handle);
+#else
+ ACE_OS::printf ("(%u)", handle);
+#endif /* ! linux */
+ ACE_OS::printf (" errno = %d, lineno = %d, flags = %d\n",
+ tss_error->error (),
+ tss_error->line (),
+ tss_error->flags ());
+ }
+ key = ACE_OS::NULL_key;
+
+ if (ACE_Thread::keycreate (&key, cleanup) == -1)
+ ACE_ERROR ((LM_ERROR,
+ "(%t) %p\n",
+ "ACE_Thread::keycreate"));
+
+ ACE_NEW_RETURN (ip,
+ int,
+ 0);
+
+ ACE_DEBUG ((LM_DEBUG,
+ "(%t) in worker 2, key = %d, ip = %x\n",
+ key,
+ ip));
+
+ if (ACE_Thread::setspecific (key, (void *) ip) == -1)
+ ACE_ERROR ((LM_ERROR,
+ "(%t) %p\n",
+ "ACE_Thread::setspecific"));
+
+ if (ACE_Thread::getspecific (key, (void **) &ip) == -1)
+ ACE_ERROR ((LM_ERROR,
+ "(%t) %p\n",
+ "ACE_Thread::setspecific"));
+
+ if (ACE_Thread::setspecific (key, (void *) 0) == -1)
+ ACE_ERROR ((LM_ERROR,
+ "(%t) %p\n",
+ "ACE_Thread::setspecific"));
+ delete ip;
+
+ if (ACE_Thread::keyfree (key) == -1)
+ ACE_ERROR ((LM_ERROR,
+ "(%t) %p\n",
+ "ACE_Thread::keyfree"));
+ }
+
+ ACE_DEBUG ((LM_DEBUG,
+ "(%t) exiting\n"));
+ return 0;
+}
+
+extern "C" void
+handler (int signum)
+{
+ ACE_DEBUG ((LM_DEBUG,
+ "signal = %S\n", signum));
+ ACE_Thread_Manager::instance ()->exit (0);
+}
+
+int
+ACE_TMAIN (int argc, ACE_TCHAR *argv[])
+{
+ // The Service_Config must be the first object defined in main...
+ ACE_Service_Config daemon (argv[0]);
+
+ int threads = argc > 1 ? ACE_OS::atoi (argv[1]) : 4;
+ int count = argc > 2 ? ACE_OS::atoi (argv[2]) : 10000;
+
+ // Register a signal handler.
+ ACE_Sig_Action sa ((ACE_SignalHandler) (handler), SIGINT);
+ ACE_UNUSED_ARG (sa);
+
+#if defined (ACE_HAS_THREADS)
+ if (ACE_Thread_Manager::instance ()->spawn_n (threads,
+ ACE_THR_FUNC (&worker),
+ reinterpret_cast<void *> (count),
+ THR_BOUND | THR_DETACHED) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%p\n",
+ "ACE_Thread_Manager::spawn_n"),
+ -1);
+
+ ACE_Thread_Manager::instance ()->wait ();
+#else
+ worker ((void *) count);
+#endif /* ACE_HAS_THREADS */
+ return 0;
+}
+
+#else
+int
+ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "ACE doesn't support support threads on this platform (yet)\n"),
+ -1);
+}
+#endif /* ACE_HAS_THREADS */
diff --git a/ACE/examples/Threads/thread_specific.h b/ACE/examples/Threads/thread_specific.h
new file mode 100644
index 00000000000..1ae48ee114f
--- /dev/null
+++ b/ACE/examples/Threads/thread_specific.h
@@ -0,0 +1,53 @@
+// $Id$
+
+#ifndef ACE_THREAD_SPECIFIC_H
+
+#include "ace/Guard_T.h"
+#include "ace/Thread_Mutex.h"
+
+// Define a class that will be stored in thread-specific data. Note
+// that as far as this class is concerned it's just a regular C++
+// class. The ACE_TSS wrapper transparently ensures that objects of
+// this class will be placed in thread-specific storage. All calls on
+// ACE_TSS::operator->() are delegated to the appropriate method in
+// the Errno class.
+
+class Errno
+{
+public:
+ int error (void) { return this->errno_; }
+ void error (int i) { this->errno_ = i; }
+
+ int line (void) { return this->lineno_; }
+ void line (int l) { this->lineno_ = l; }
+
+ // Errno::flags_ is a static variable, so we've got to protect it
+ // with a mutex since it isn't kept in thread-specific storage.
+ int flags (void)
+ {
+ ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, Errno::lock_, -1);
+
+ return Errno::flags_;
+ }
+
+ void flags (int f)
+ {
+ ACE_GUARD (ACE_Thread_Mutex, ace_mon, Errno::lock_);
+
+ Errno::flags_ = f;
+ }
+
+private:
+ // = errno_ and lineno_ will be thread-specific data so they don't
+ // need a lock.
+ int errno_;
+ int lineno_;
+
+ static int flags_;
+#if defined (ACE_HAS_THREADS)
+ // flags_ needs a lock.
+ static ACE_Thread_Mutex lock_;
+#endif /* ACE_HAS_THREADS */
+};
+
+#endif /* ACE_THREAD_SPECIFIC_H */
diff --git a/ACE/examples/Threads/token.cpp b/ACE/examples/Threads/token.cpp
new file mode 100644
index 00000000000..bbda579369b
--- /dev/null
+++ b/ACE/examples/Threads/token.cpp
@@ -0,0 +1,78 @@
+// $Id$
+
+// Test out the ACE Token class.
+
+#include "ace/OS_main.h"
+#include "ace/Token.h"
+#include "ace/Task.h"
+#include "ace/OS_NS_time.h"
+
+ACE_RCSID(Threads, token, "$Id$")
+
+#if defined (ACE_HAS_THREADS)
+
+class My_Task : public ACE_Task<ACE_MT_SYNCH>
+{
+public:
+ My_Task (int n);
+ virtual int svc (void);
+
+ static void sleep_hook (void *);
+
+private:
+ ACE_Token token_;
+};
+
+My_Task::My_Task (int n)
+{
+ // Make this Task into an Active Object.
+ this->activate (THR_BOUND | THR_DETACHED, n);
+
+ // Wait for all the threads to exit.
+ this->thr_mgr ()->wait ();
+}
+
+void
+My_Task::sleep_hook (void *)
+{
+ ACE_DEBUG ((LM_ERROR, "(%u) blocking, My_Task::sleep_hook () called\n",
+ ACE_Thread::self())) ;
+}
+
+// Test out the behavior of the ACE_Token class.
+
+int
+My_Task::svc (void)
+{
+ for (size_t i = 0; i < 100; i++)
+ {
+ // Wait for up to 1 millisecond past the current time to get the token.
+ ACE_Time_Value timeout (ACE_OS::time (0), 1000);
+
+ if (this->token_.acquire (&My_Task::sleep_hook, 0, &timeout) == 1)
+ {
+ this->token_.acquire ();
+ this->token_.renew ();
+ this->token_.release ();
+ this->token_.release ();
+ }
+ else
+ ACE_Thread::yield ();
+ }
+ return 0;
+}
+
+int
+ACE_TMAIN (int argc, ACE_TCHAR *argv[])
+{
+ My_Task tasks (argc > 1 ? ACE_OS::atoi (argv[1]) : 4);
+
+ return 0;
+}
+#else
+int
+ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ ACE_ERROR_RETURN ((LM_ERROR, "your platform doesn't support threads\n"), -1);
+}
+#endif /* */
diff --git a/ACE/examples/Threads/tss1.cpp b/ACE/examples/Threads/tss1.cpp
new file mode 100644
index 00000000000..783d4dc5b7a
--- /dev/null
+++ b/ACE/examples/Threads/tss1.cpp
@@ -0,0 +1,157 @@
+// $Id$
+
+// ============================================================================
+//
+// = LIBRARY
+// tests
+//
+// = FILENAME
+// TSS_Test.cpp
+//
+// = DESCRIPTION
+// This program tests thread specific storage of data. The ACE_TSS
+// wrapper transparently ensures that the objects of this class
+// will be placed in thread-specific storage. All calls on
+// ACE_TSS::operator->() are delegated to the appropriate method
+// in the Errno class. Note that each thread of control has its
+// own unique TSS object.
+//
+// = AUTHOR
+// Detlef Becker <Detlef.Becker@med.siemens.de>
+//
+// ============================================================================
+
+#include "ace/OS_main.h"
+#include "ace/Service_Config.h"
+#include "ace/Task.h"
+
+ACE_RCSID(Threads, tss1, "$Id$")
+
+#if defined (ACE_HAS_THREADS)
+
+#include "thread_specific.h"
+
+// (Sun C++ 4.2 with -O3 won't link if the following is not const.)
+static const int iterations = 100;
+
+// Static variables.
+ACE_MT (ACE_Thread_Mutex Errno::lock_);
+int Errno::flags_;
+
+// This is our thread-specific error handler...
+// (Sun C++ 4.2 with -O3 won't link if the following is static.)
+ACE_TSS<Errno> TSS_Error;
+
+#if defined (ACE_HAS_THREADS)
+ typedef ACE_TSS_Guard<ACE_Thread_Mutex> GUARD;
+#else
+ typedef ACE_Guard<ACE_Null_Mutex> GUARD;
+#endif /* ACE_HAS_THREADS */
+
+// Keeps track of whether Tester::close () has started.
+// (Sun C++ 4.2 with -O3 won't link if the following is static.)
+int close_started = 0;
+
+template <ACE_SYNCH_DECL>
+class Tester: public ACE_Task<ACE_SYNCH_USE>
+{
+public:
+ Tester (void) {}
+ ~Tester (void) {}
+
+ virtual int svc (void);
+
+ virtual int open (void *args = 0);
+ // Activate the thread.
+
+ virtual int close (u_long args = 0);
+};
+
+template <ACE_SYNCH_DECL> int
+Tester<ACE_SYNCH_USE>::svc (void)
+{
+ ACE_DEBUG ((LM_DEBUG,
+ "(%t) svc: setting error code to 1\n"));
+ TSS_Error->error (1);
+
+ for (int i = 0; i < iterations; i++)
+ // Print out every tenth iteration.
+ if ((i % 10) == 1)
+ ACE_DEBUG ((LM_DEBUG,
+ "(%t) error = %d\n",
+ TSS_Error->error ()));
+ this->close ();
+
+ return 0;
+}
+
+template <ACE_SYNCH_DECL> int
+Tester<ACE_SYNCH_USE>::open (void *)
+{
+ // Make this an Active Object.
+ return this->activate ();
+}
+
+template <ACE_SYNCH_DECL>
+int Tester<ACE_SYNCH_USE>::close (u_long)
+{
+ ACE_DEBUG ((LM_DEBUG,
+ "(%t) close running\n"));
+ close_started = 1;
+ ACE_DEBUG ((LM_DEBUG,
+ "(%t) close: setting error code to 7\n"));
+ TSS_Error->error (7);
+ ACE_DEBUG ((LM_DEBUG,
+ "(%t) close: error = %d\n",
+ TSS_Error->error ()));
+ //close_started = 0;
+ return 0;
+}
+
+int
+ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ Tester<ACE_MT_SYNCH> tester;
+
+ ACE_DEBUG ((LM_DEBUG,
+ "(%t) main: setting error code to 3\n"));
+ TSS_Error->error (3);
+ ACE_DEBUG ((LM_DEBUG,
+ "(%t) main: error = %d\n",
+ TSS_Error->error ()));
+
+ // Spawn off a thread and make test an Active Object.
+ tester.open ();
+
+ // Keep looping until <Tester::close> is called.
+ for (int i = 0; !close_started; i++) {
+ // while (!close_started)
+ if ((i % 100) == 0) {
+ ACE_DEBUG ((LM_DEBUG,
+ "(%t) error = %d\n",
+ TSS_Error->error ()));
+ }
+ }
+ ACE_DEBUG ((LM_DEBUG,
+ "(%t) main: setting error code to 4\n"));
+ TSS_Error->error (4);
+ ACE_DEBUG ((LM_DEBUG,
+ "(%t) main: error = %d\n",
+ TSS_Error->error ()));
+
+ // Keep looping until <Tester::close> finishes.
+ while (close_started != 0)
+ ACE_DEBUG ((LM_DEBUG,
+ "(%t) error = %d\n",
+ TSS_Error->error ()));
+ return 0;
+}
+#else
+int
+ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "ACE doesn't support support threads on this platform (yet)\n"),
+ -1);
+}
+#endif /* ACE_HAS_THREADS */
diff --git a/ACE/examples/Threads/tss2.cpp b/ACE/examples/Threads/tss2.cpp
new file mode 100644
index 00000000000..0c7fb9ac3ee
--- /dev/null
+++ b/ACE/examples/Threads/tss2.cpp
@@ -0,0 +1,190 @@
+// $Id$
+
+// ============================================================================
+//
+// = LIBRARY
+// tests
+//
+// = FILENAME
+// TSS_Test.cpp
+//
+// = DESCRIPTION
+// This program tests various features of ACE_Thread and the
+// thread-specific storage variant of <ACE_Singleton>.
+//
+// = AUTHOR
+// Prashant Jain and Doug Schmidt
+//
+// ============================================================================
+
+#include "ace/OS_main.h"
+#include "ace/Thread.h"
+#include "ace/Log_Msg.h"
+#include "ace/Atomic_Op.h"
+#include "TSS_Data.h"
+#include "TSS_Obj.h"
+#include "TSS_Task.h"
+
+ACE_RCSID(Threads, tss2, "$Id$")
+
+#if defined (ACE_HAS_THREADS)
+
+const int MAX_TASKS = 4;
+const int MAX_ITERATIONS = 10;
+
+ACE_Atomic_Op<ACE_Token, int> Test_Task::count_ (0);
+ACE_Atomic_Op<ACE_Token, int> Test_Task::wait_count_ (0);
+ACE_Atomic_Op<ACE_Token, int> Test_Task::max_count_ (0);
+int num_tasks = 0;
+
+// ACE synchronization object.
+static ACE_Token token;
+
+ACE_Atomic_Op<ACE_Thread_Mutex, int> TSS_Obj::count_ = 0;
+
+TSS_Obj::TSS_Obj (void)
+{
+ TSS_Obj::count_++;
+ ACE_DEBUG ((LM_DEBUG, "(%t) TSS_Obj+: %d\n", TSS_Obj::count_.value ()));
+}
+
+TSS_Obj::~TSS_Obj (void)
+{
+ TSS_Obj::count_--;
+ ACE_DEBUG ((LM_DEBUG, "(%t) TSS_Obj-: %d\n", TSS_Obj::count_.value ()));
+}
+
+Test_Task::Test_Task (void)
+{
+ Test_Task::count_++;
+ ACE_DEBUG ((LM_DEBUG,
+ "(%t) Test_Task+: %d\n", Test_Task::count_.value ()));
+}
+
+Test_Task::~Test_Task (void)
+{
+ Test_Task::count_--;
+
+ ACE_DEBUG ((LM_DEBUG,
+ "(%t) Test_Task-: %d\n", Test_Task::count_.value ()));
+ Test_Task::wait_count_--;
+}
+
+void *
+Test_Task::svc (void *arg)
+{
+ // When the thread exits this thread-specific object will be deleted
+ // automatically.
+ ACE_TSS<TSS_Obj> tss (new TSS_Obj);
+
+ TSS_DATA::instance ()->data (arg);
+
+ Test_Task::wait_count_++;
+ Test_Task::max_count_++;
+
+ ACE_DEBUG ((LM_DEBUG, "(%t) svc: waiting (data = %u)\n",
+ arg));
+
+ // Do a bunch of set operations on the TSS data just to make sure
+ // that it's truly in TSS (it it weren't, the assertion would fail).
+
+ while (Test_Task::max_count_ < num_tasks)
+ {
+ TSS_DATA::instance ()->data (arg);
+ ACE_Thread::yield ();
+ }
+
+ ACE_DEBUG ((LM_DEBUG, "(%t) svc: waiting finished (data = %u)\n",
+ arg));
+
+#if 0
+ ACE_ASSERT (TSS_DATA::instance ()->data () == arg);
+#endif
+
+ delete (Test_Task *) arg;
+
+ return 0;
+}
+
+int
+Test_Task::open (void *arg)
+{
+ if (ACE_Thread::spawn ((ACE_THR_FUNC) Test_Task::svc, arg) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "ACE_Thread::spawn"), 0);
+
+ return 0;
+}
+
+int
+ACE_TMAIN (int argc, ACE_TCHAR *argv[])
+{
+ num_tasks = argc > 1 ? ACE_OS::atoi (argv[1]) : MAX_TASKS;
+
+ Test_Task **task_arr = 0;
+
+ ACE_NEW_RETURN (task_arr, Test_Task *[num_tasks], -1);
+
+ for (int i = 0; i < MAX_ITERATIONS; i++)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ "(%t) ********* iteration %d **********\n"
+ "Test_Task::max_count_ %d\n",
+ i,
+ Test_Task::max_count_.value ()));
+ Test_Task::max_count_ = 0;
+
+ for (int j = 0; j < num_tasks; j++)
+ {
+ ACE_NEW_RETURN (task_arr[j], Test_Task, -1);
+ task_arr[j]->open (task_arr[j]);
+ }
+
+ ACE_DEBUG ((LM_DEBUG, "(%t) waiting for first thread started\n"));
+
+ for (;;)
+ {
+ ACE_Thread::yield ();
+
+ if (Test_Task::max_count_ != 0 )
+ break;
+ }
+
+ ACE_DEBUG ((LM_DEBUG, "(%t) First thread started\n"
+ "Waiting for all threads finished\n"));
+
+ for (;;)
+ {
+ if (!(Test_Task::max_count_ == num_tasks
+ && Test_Task::wait_count_ == 0))
+ {
+ ACE_Thread::yield ();
+ continue;
+ }
+ ACE_DEBUG ((LM_DEBUG,
+ "(%t) Test_Task::max_count_ = %d,"
+ " Test_Task::wait_count_ = %d",
+ Test_Task::max_count_.value (),
+ Test_Task::wait_count_.value ()));
+ break;
+ }
+
+ ACE_DEBUG ((LM_DEBUG, "(%t) all threads finished\n"));
+ }
+
+ return 0;
+}
+
+#if defined (ACE_HAS_EXPLICIT_STATIC_TEMPLATE_MEMBER_INSTANTIATION)
+template ACE_TSS_Singleton<TSS_Data, ACE_SYNCH_MUTEX> *
+ ACE_TSS_Singleton<TSS_Data, ACE_SYNCH_MUTEX>::singleton_;
+#endif /* ACE_HAS_EXPLICIT_STATIC_TEMPLATE_MEMBER_INSTANTIATION */
+
+#else
+
+int
+ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ ACE_ERROR ((LM_ERROR, "threads not supported on this platform\n"));
+ return 0;
+}
+#endif /* ACE_HAS_THREADS */
diff --git a/ACE/examples/Threads/wfmo.cpp b/ACE/examples/Threads/wfmo.cpp
new file mode 100644
index 00000000000..bfd451444b1
--- /dev/null
+++ b/ACE/examples/Threads/wfmo.cpp
@@ -0,0 +1,132 @@
+// $Id$
+
+// This test program illustrates that the Win32
+// <WaitForMultipleObjects> function can be called in multiple
+// threads, all of which wait on the same set of HANDLEs. Note that
+// the dispatching of the threads should be relatively "fair" (i.e.,
+// everyone gets a chance to process the various HANDLEs as they
+// become active). Thanks to Ari Erev <Ari_Erev@comverse.com> for
+// suggesting this and providing the initial code.
+
+#include "ace/Task.h"
+#include "ace/OS_NS_unistd.h"
+#include "ace/OS_main.h"
+
+ACE_RCSID(Threads, wfmo, "$Id$")
+
+#if defined (ACE_WIN32)
+
+// Number of threads.
+static const int THREAD_COUNT = 5;
+
+// Number of iterations.
+static const int MAX_ITERATIONS = 100;
+
+class WFMO_Test : public ACE_Task <ACE_NULL_SYNCH>
+{
+public:
+ virtual int open (void *);
+ virtual int svc (void);
+
+ // Use two handles here..
+ ACE_sema_t sema_handles_[2];
+ int semaphore_count_;
+};
+
+static WFMO_Test wfmo_test;
+
+int
+WFMO_Test::open (void *arg)
+{
+ int thread_count = int (arg);
+ int result = this->activate (0, thread_count);
+
+ ACE_ASSERT (result != -1);
+ return 0;
+}
+
+int
+WFMO_Test::svc (void)
+{
+ while(1)
+ {
+ int result = ::WaitForMultipleObjects (2, this->sema_handles_,
+ FALSE, INFINITE);
+ if (result == WAIT_OBJECT_0)
+ {
+ // Signal the other semaphore just to see if we can get
+ // another thread to wakeup.
+ result = ACE_OS::sema_post (&sema_handles_[1]);
+ ACE_ASSERT (result != -1);
+ }
+ else if (result == WAIT_OBJECT_0 + 1)
+ ;
+ else
+ {
+ ACE_ERROR ((LM_ERROR, "Error in WaitForMultipleObejcts\n"));
+ ACE_OS::exit (0);
+ }
+
+ // semaphore_count_ will be displayed by the "main" thread.
+ // It's value must be 2. Note that although this is a shared
+ // resource it's not protected via a mutex because the ++
+ // operation on Intel is atomic.
+
+ semaphore_count_++;
+ ACE_DEBUG ((LM_DEBUG,
+ "(%t) thread has been signaled.\n"));
+
+ // Yield this thread so that the other one(s) have a chance to
+ // run.
+ ACE_OS::thr_yield ();
+ }
+
+ return 0;
+}
+
+int
+ACE_TMAIN (int argc, ACE_TCHAR *argv[])
+{
+ int thread_count = THREAD_COUNT;
+
+ if (argc > 1)
+ thread_count = ACE_OS::atoi (argv[1]);
+
+ wfmo_test.open ((void *) thread_count);
+
+ // Initialize the semaphores.
+ int result = ACE_OS::sema_init (&wfmo_test.sema_handles_[0], thread_count + 5);
+ ACE_ASSERT (result != -1);
+
+ result = ACE_OS::sema_init (&wfmo_test.sema_handles_[1], thread_count + 5);
+ ACE_ASSERT (result != -1);
+
+ for (int i = 0; i < MAX_ITERATIONS; i++)
+ {
+ wfmo_test.semaphore_count_ = 0;
+
+ result = ACE_OS::sema_post (&wfmo_test.sema_handles_[0]);
+ ACE_ASSERT (result != -1);
+
+ // No real synchronization here. Just sleep enough so that at
+ // least one (or two threads) run as a result of the semaphore.
+ ACE_OS::sleep (1);
+
+ // Add one for the other thread that was signaled.
+ ACE_DEBUG ((LM_DEBUG,
+ "semaphore_count_ = %d (should have been %d).\n",
+ wfmo_test.semaphore_count_,
+ 2)); // Two semaphores should have been released.
+ }
+
+ ACE_OS::exit (0);
+
+ return 0;
+}
+#else
+int
+ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ ACE_DEBUG ((LM_DEBUG, "this test only runs on Win32\n"));
+}
+#endif /* ACE_WIN32 */
diff --git a/ACE/examples/Timer_Queue/.cvsignore b/ACE/examples/Timer_Queue/.cvsignore
new file mode 100644
index 00000000000..6f1917f64c8
--- /dev/null
+++ b/ACE/examples/Timer_Queue/.cvsignore
@@ -0,0 +1,3 @@
+Asynch_Timer_Queue_Test
+Reactor_Timer_Queue_Test
+Thread_Timer_Queue_Test
diff --git a/ACE/examples/Timer_Queue/Async_Timer_Queue_Test.cpp b/ACE/examples/Timer_Queue/Async_Timer_Queue_Test.cpp
new file mode 100644
index 00000000000..18d12b8017a
--- /dev/null
+++ b/ACE/examples/Timer_Queue/Async_Timer_Queue_Test.cpp
@@ -0,0 +1,299 @@
+// $Id$
+
+// ============================================================================
+//
+// = LIBRARY
+// examples
+//
+// = FILENAME
+// Async_Timer_Queue_Test.cpp
+//
+// = DESCRIPTION
+// This test exercises the <ACE_Asynch_Timer_Queue_Adapter>
+// using an <ACE_Timer_Heap>.
+//
+// = AUTHORS
+// Douglas C. Schmidt <schmidt@cs.wustl.edu> and
+// Sergio Flores-Gaitan <sergio@cs.wustl.edu>
+//
+// ============================================================================
+
+#include "ace/OS_NS_sys_time.h"
+#include "ace/Signal.h"
+#include "ace/Timer_Heap.h"
+#include "ace/Timer_Queue_Adapters.h"
+
+#include "Async_Timer_Queue_Test.h"
+
+ACE_RCSID(Timer_Queue, Async_Timer_Queue_Test, "$Id$")
+
+// Hook method that is called to handle the expiration of a timer.
+int
+Async_Timer_Handler::handle_timeout (const ACE_Time_Value &tv,
+ const void *arg)
+{
+ // Print some information here (note that this is not strictly
+ // signal-safe since the ACE logging mechanism uses functions that
+ // aren't guaranteed to work in all signal handlers).
+ ACE_DEBUG ((LM_DEBUG,
+ "handle_timeout() = (%d, %d) %d\n",
+ tv.sec (),
+ tv.usec (),
+ arg));
+
+ // Commit suicide!
+ delete this;
+ return 0;
+}
+
+// Initialize the Singleton pointer.
+Async_Timer_Queue *Async_Timer_Queue::instance_ = 0;
+
+// Implement the Singleton logic.
+Async_Timer_Queue *
+Async_Timer_Queue::instance (void)
+{
+ if (Async_Timer_Queue::instance_ == 0)
+ {
+ // Initialize with all signals enabled.
+ ACE_Sig_Set ss (1);
+
+ // But, don't block out SIGQUIT since we always want that
+ // signal to interrupt the program.
+ ss.sig_del (SIGQUIT);
+
+ ACE_NEW_RETURN (Async_Timer_Queue::instance_,
+ Async_Timer_Queue (&ss),
+ 0);
+ }
+ return Async_Timer_Queue::instance_;
+}
+
+// Sets the signal set to mask, for the timer queue.
+
+Async_Timer_Queue::Async_Timer_Queue (ACE_Sig_Set *ss)
+ : tq_ (ss)
+{
+}
+
+// Dump the contents of the queue when we receive ^C.
+
+void
+Async_Timer_Queue::dump (void)
+{
+ ACE_DEBUG ((LM_DEBUG, "begin dumping timer queue\n"));
+
+ // This iterator is implicitly protected since SIGINT and SIGALRM
+ // signals cannot occur while it is running.
+
+ for (ACE_Timer_Heap_Iterator iter (this->tq_.timer_queue ());
+ iter.item () != 0;
+ iter.next ())
+ iter.item ()->dump ();
+
+ ACE_DEBUG ((LM_DEBUG,
+ "end dumping timer queue\n"));
+}
+
+// Schedule a timer.
+
+void
+Async_Timer_Queue::schedule (u_int microsecs)
+{
+ ACE_Time_Value tv (0, microsecs);
+
+ // Create a new Event_Handler for our timer.
+
+ ACE_Event_Handler *eh;
+ ACE_NEW (eh,
+ Async_Timer_Handler);
+
+ // Schedule the timer to run in the future.
+ long tid = this->tq_.schedule
+ (eh,
+ 0, // Note that our "magic cookie" ACT is always NULL.
+ ACE_OS::gettimeofday () + tv);
+
+ if (tid == -1)
+ ACE_ERROR ((LM_ERROR,
+ "%p\n",
+ "schedule_timer"));
+}
+
+// Cancel a timer.
+
+void
+Async_Timer_Queue::cancel (long timer_id)
+{
+ ACE_DEBUG ((LM_DEBUG,
+ "canceling %d\n",
+ timer_id));
+
+ const void *act = 0;
+
+ if (this->tq_.cancel (timer_id, &act) == -1)
+ ACE_ERROR ((LM_ERROR,
+ "%p\n",
+ "cancel_timer"));
+
+ // In this case, the act will be 0, but it could be a real pointer
+ // in other cases.
+ delete (ACE_Event_Handler *) act;
+}
+
+// Schedule timer hook method. This method is called from the driver.
+
+int
+Async_Timer_Queue::schedule_timer (void *argument)
+{
+ u_long useconds = *(int *)argument;
+
+ // Schedule a timer.
+ Async_Timer_Queue::instance ()->schedule (useconds);
+
+ return 0;
+}
+
+// Cancel timer hook method. Is called from the driver class.
+
+int
+Async_Timer_Queue::cancel_timer (void *argument)
+{
+ u_long id = *(int *)argument;
+
+ // Cancel a timer.
+ Async_Timer_Queue::instance ()->cancel (id);
+
+ return 0;
+}
+
+// Dummy list timer hook method. The listing of timers is done from a
+// signal handler using SIGINT, not from the driver.
+
+int
+Async_Timer_Queue::list_timer (void *)
+{
+ // Display an error message.
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "invalid input\n"), 0);
+}
+
+// Dummy shutdown timer hook method. The shutdown of the timer queue
+// is done with a signal handler using SIGQUIT, not from the driver.
+
+int
+Async_Timer_Queue::shutdown_timer (void *)
+{
+ // Display an error message.
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "invalid input\n"),
+ 0);
+}
+
+// Handler for the SIGINT and SIGQUIT signals.
+
+static void
+signal_handler (int signum)
+{
+ ACE_DEBUG ((LM_DEBUG,
+ "handling signal %S\n",
+ signum));
+
+ switch (signum)
+ {
+ case SIGINT:
+ Async_Timer_Queue::instance ()->dump ();
+ break;
+ /* NOTREACHED */
+
+ case SIGQUIT:
+ ACE_ERROR ((LM_ERROR,
+ "shutting down on SIGQUIT%a\n",
+ 1));
+ /* NOTREACHED */
+ break;
+ }
+}
+
+// Register the signal handlers for SIGQUIT and SIGINT. We must
+// ensure that the SIGINT handler isn't interrupted by SIGALRM.
+// However, SIGQUIT is never blocked...
+
+static void
+register_signal_handlers (void)
+{
+ // Register SIGQUIT (never blocked).
+ ACE_Sig_Action sigquit ((ACE_SignalHandler) signal_handler,
+ SIGQUIT);
+ ACE_UNUSED_ARG (sigquit);
+
+ // Don't let the SIGALRM interrupt the SIGINT handler!
+ ACE_Sig_Set ss;
+ ss.sig_add (SIGALRM);
+
+ // Register SIGINT (note that system calls will be restarted
+ // automatically).
+ ACE_Sig_Action sigint ((ACE_SignalHandler) signal_handler,
+ SIGINT,
+ ss,
+ SA_RESTART);
+ ACE_UNUSED_ARG (sigint);
+}
+
+// constructor
+
+Async_Timer_Queue_Test_Driver::Async_Timer_Queue_Test_Driver (void)
+{
+}
+
+// displays the menu of options.
+
+int
+Async_Timer_Queue_Test_Driver::display_menu (void)
+{
+ // The menu of options provided to the user.
+ static char menu[] =
+ "****\n"
+ "1) schedule timer <usecs> \n"
+ "2) cancel timer <timer_id>\n"
+ "^C list timers\n"
+ "^\\ exit program\n";
+
+ ACE_DEBUG ((LM_DEBUG,
+ "%s",
+ menu));
+ return 0;
+}
+
+// Initializes the test driver.
+
+int
+Async_Timer_Queue_Test_Driver::init (void)
+{
+ typedef Command<Async_Timer_Queue, Async_Timer_Queue::ACTION> CMD;
+
+ // Initialize <Command> objects with their corresponding <Input_Task> methods.
+ ACE_NEW_RETURN (schedule_cmd_,
+ CMD (*Async_Timer_Queue::instance (),
+ &Async_Timer_Queue::schedule_timer),
+ -1);
+
+ ACE_NEW_RETURN (cancel_cmd_,
+ CMD (*Async_Timer_Queue::instance (),
+ &Async_Timer_Queue::cancel_timer),
+ -1);
+
+ ACE_NEW_RETURN (list_cmd_,
+ CMD (*Async_Timer_Queue::instance (),
+ &Async_Timer_Queue::list_timer),
+ -1);
+
+ ACE_NEW_RETURN (shutdown_cmd_,
+ CMD (*Async_Timer_Queue::instance (),
+ &Async_Timer_Queue::shutdown_timer),
+ -1);
+
+ register_signal_handlers ();
+
+ return 0;
+}
diff --git a/ACE/examples/Timer_Queue/Async_Timer_Queue_Test.h b/ACE/examples/Timer_Queue/Async_Timer_Queue_Test.h
new file mode 100644
index 00000000000..6b166f894c3
--- /dev/null
+++ b/ACE/examples/Timer_Queue/Async_Timer_Queue_Test.h
@@ -0,0 +1,119 @@
+/* -*- C++ -*- */
+
+// $Id$
+
+// ============================================================================
+//
+// = LIBRARY
+// examples
+//
+// = FILENAME
+// Async_Timer_Queue_Test.h
+//
+// = DESCRIPTION
+// This test exercises the <ACE_Asynch_Timer_Queue_Adapter>
+// using an <ACE_Timer_Heap>.
+//
+// = AUTHORS
+// Douglas C. Schmidt and
+// Sergio Flores-Gaitan
+// ============================================================================
+
+#ifndef _ASYNC_TIMER_QUEUE_TEST_H_
+#define _ASYNC_TIMER_QUEUE_TEST_H_
+
+#include "ace/Signal.h"
+#include "ace/svc_export.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/Timer_Heap.h"
+#include "ace/Timer_Queue_Adapters.h"
+
+#include "Driver.h"
+
+class Async_Timer_Handler : public ACE_Event_Handler
+{
+ // = TITLE
+ // Target of the asynchronous timeout operation.
+public:
+ virtual int handle_timeout (const ACE_Time_Value &tv,
+ const void *arg);
+ // Callback hook invoked by the <Timer_Queue>.
+};
+
+class Async_Timer_Queue
+{
+ // = TITLE
+ // Asynchronous Timer Queue Singleton.
+ //
+ // = DESCRIPTION
+ // We use this class to avoid global variables and to
+ // consolidate all the Timer Queue processing in one central
+ // place.
+public:
+ typedef int (Async_Timer_Queue::*ACTION) (void *);
+
+ static Async_Timer_Queue *instance (void);
+ // Singleton access point.
+
+ void schedule (u_int microsecs);
+ // Schedule a timer to expire <microsecs> in the future.
+
+ void cancel (long timer_id);
+ // Cancel a timer with <timer_id>.
+
+ void dump (void);
+ // Dump the contents of the queue.
+
+ int schedule_timer (void *argument);
+ // hook method to schedule a timer. Called from
+ // <Timer_Queue_Test_Driver>
+
+ int cancel_timer (void *argument);
+ // hook method to cancel a timer. Called from
+ // <Timer_Queue_Test_Driver>
+
+ int list_timer (void *argument);
+ // hook method to list timers. Called from
+ // <Timer_Queue_Test_Driver>
+
+ int shutdown_timer (void *argument);
+ // hook method to exit the timer queue. Called from
+ // <Timer_Queue_Test_Driver>
+
+private:
+ Async_Timer_Queue (ACE_Sig_Set *);
+ // Private constructor enforces the Singleton.
+
+ static Async_Timer_Queue *instance_;
+ // Pointer to the timer queue.
+
+ ACE_Async_Timer_Queue_Adapter<ACE_Timer_Heap> tq_;
+ // The adapter is instantiated by an <ACE_Timer_Heap>.
+};
+
+class ACE_Svc_Export Async_Timer_Queue_Test_Driver : public Timer_Queue_Test_Driver <Async_Timer_Queue *, Async_Timer_Queue, Async_Timer_Queue::ACTION>
+{
+ // = TITLE
+ // Async_Timer_Queue_Test_Driver
+ //
+ // = DESCRIPTION
+ // This class implements a test driver for the
+ // <Async_Timer_Queue>. Implements a display_menu() method that
+ // prints the options for a user. and init() which initializes
+ // the driver. The rest of the common functionality is in the
+ // parent class <Timer_Queue_Test_Driver>.
+public:
+ Async_Timer_Queue_Test_Driver (void);
+
+ virtual int display_menu (void);
+ // Print menu of options.
+
+ virtual int init (void);
+ // Initializes the driver's internal variables inherited from the parent
+};
+
+#endif /* _ASYNC_TIMER_QUEUE_TEST_H_ */
diff --git a/ACE/examples/Timer_Queue/Driver.cpp b/ACE/examples/Timer_Queue/Driver.cpp
new file mode 100644
index 00000000000..ca549b1f952
--- /dev/null
+++ b/ACE/examples/Timer_Queue/Driver.cpp
@@ -0,0 +1,164 @@
+// $Id$
+
+// ============================================================================
+// = LIBRARY
+// examples
+//
+// = FILENAME
+// Driver.cpp
+//
+// = DESCRIPTION
+// This code builds an abstraction to factor out common code for
+// the different implementations of the Timer_Queue.
+//
+// = AUTHOR
+// Douglas Schmidt <schmidt@cs.wustl.edu> &&
+// Sergio Flores-Gaitan <sergio@cs.wustl.edu>
+//
+// ============================================================================
+
+#if !defined (_DRIVER_CPP_)
+#define _DRIVER_CPP_
+
+#include "ace/OS_NS_stdio.h"
+#include "ace/OS_NS_string.h"
+#include "ace/OS_NS_unistd.h"
+#include "ace/Auto_Ptr.h"
+#include "Driver.h"
+
+ACE_RCSID(Timer_Queue, Driver, "$Id$")
+
+// constructor
+
+template <class RECEIVER, class ACTION>
+Command<RECEIVER, ACTION>::Command (RECEIVER &recvr,
+ ACTION action)
+ : receiver_ (recvr),
+ action_ (action)
+{
+}
+
+// destructor
+template <class RECEIVER, class ACTION>
+Command<RECEIVER, ACTION>::~Command (void)
+{
+}
+
+// invokes an operation.
+
+template <class RECEIVER, class ACTION> int
+Command<RECEIVER, ACTION>::execute (void *arg)
+{
+ return (receiver_.*action_) (arg);
+}
+
+// gets the next request from the user input.
+
+template <class TQ, class RECEIVER, class ACTION>
+Timer_Queue_Test_Driver<TQ, RECEIVER, ACTION>::~Timer_Queue_Test_Driver (void)
+{
+}
+
+template <class TQ, class RECEIVER, class ACTION> int
+Timer_Queue_Test_Driver<TQ, RECEIVER, ACTION>::get_next_request (void)
+{
+ char buf[BUFSIZ];
+
+ this->display_menu ();
+
+ ACE_OS::printf ("please enter your choice: ");
+ ACE_OS::fflush (stdout);
+
+ // reads input from the user
+ if (this->read_input (buf, sizeof buf) <= 0)
+ return -1;
+
+ // Parse and run the command.
+ return this->parse_commands (buf);
+}
+
+// Runs the test.
+
+template <class TQ, class RECEIVER, class ACTION> int
+Timer_Queue_Test_Driver<TQ, RECEIVER, ACTION>::run_test (void)
+{
+ this->init ();
+
+ for (;;)
+ if (this->get_next_request () == -1)
+ return -1;
+
+ ACE_NOTREACHED (return 0);
+}
+
+// Reads input from the user from ACE_STDIN into the buffer specified.
+
+template <class TQ, class RECEIVER, class ACTION> ssize_t
+Timer_Queue_Test_Driver<TQ, RECEIVER, ACTION>::read_input (char *buf, size_t bufsiz)
+{
+ ACE_OS::memset (buf, 0, bufsiz);
+
+ // Wait for user to type commands. This call is automatically
+ // restarted when SIGINT or SIGALRM signals occur.
+ return ACE_OS::read (ACE_STDIN, buf, bufsiz);
+}
+
+// Parse the input and executes the corresponding operation
+
+template <class TQ, class RECEIVER, class ACTION> int
+Timer_Queue_Test_Driver<TQ, RECEIVER, ACTION>::parse_commands (const char *buf)
+{
+ int option;
+
+ if (::sscanf (buf, "%d", &option) <= 0)
+ // If there was an error reading the option simply try on the next line.
+ return 0;
+
+ switch (option)
+ {
+ case 1: // Schedule a new timer.
+ {
+ u_long useconds;
+ // We just reread the option, this simplies parsing (since
+ // sscanf can do it for us.)
+ if (::sscanf (buf, "%d %lu", &option, &useconds) < 2)
+ return 0;
+
+ if (schedule_cmd_->execute ((void *) &useconds) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, "%t %p\n", "new timer failed"), -1);
+ }
+ break; // Cancel an existing timer.
+ /* NOTREACHED */
+ case 2:
+ {
+ u_long id;
+ // We just reread the option, this simplies parsing (since
+ // sscanf can do it for us.)
+ if (::sscanf (buf, "%d %lu", &option, &id) < 2)
+ return 0;
+
+ if (cancel_cmd_->execute ((void *) &id) == -1)
+ ACE_DEBUG ((LM_DEBUG, "Timer #%d is not valid\n", id));
+
+ }
+ break;
+ /* NOTREACHED */
+
+ case 3: // Dump the existing timers.
+ return list_cmd_->execute (NULL);
+ /* NOTREACHED */
+
+ case 4: // Exit the program.
+ return shutdown_cmd_->execute (NULL);
+ /* NOTREACHED */
+
+ default:
+ // Display an error message.
+ ACE_ERROR_RETURN ((LM_ERROR, "invalid input %s\n", buf), 0);
+ ACE_NOTREACHED (break);
+ /* NOTREACHED */
+ }
+ return 0;
+}
+
+#endif /* _DRIVER_CPP_ */
diff --git a/ACE/examples/Timer_Queue/Driver.h b/ACE/examples/Timer_Queue/Driver.h
new file mode 100644
index 00000000000..4677b904982
--- /dev/null
+++ b/ACE/examples/Timer_Queue/Driver.h
@@ -0,0 +1,137 @@
+/* -*- C++ -*- */
+
+// $Id$
+
+// ============================================================================
+//
+// = LIBRARY
+// examples
+//
+// = FILENAME
+// Driver.h
+//
+// = DESCRIPTION
+// This code builds an abstraction to factor out common code for
+// the different implementations of the Timer_Queue.
+//
+// = AUTHORS
+// Sergio Flores-Gaitan <sergio@cs.wustl.edu>
+//
+// ============================================================================
+
+#ifndef _DRIVER_H_
+#define _DRIVER_H_
+
+#include "ace/Task.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/Timer_Heap_T.h"
+#include "ace/Timer_Queue_Adapters.h"
+
+template <class RECEIVER, class ACTION>
+class Command
+{
+ // = TITLE
+ // Defines an abstract class that allows us to invoke commands
+ // without knowing anything about the implementation. This class
+ // is used in the <Timer_Queue_Test_Driver> to invoke operations
+ // of the driver.
+ //
+ // = DESCRIPTION
+ // This class declares an interface to execute operations,
+ // binding a RECEIVER object with an ACTION. The RECEIVER knows
+ // how to implement the operation. A class can invoke operations
+ // without knowing anything about it, or how it was implemented.
+public:
+ Command (RECEIVER &recvr, ACTION action);
+ // Sets the <receiver_> of the Command to recvr, and the
+ // <action_> of the Command to <action>.
+
+ virtual ~Command (void);
+
+ virtual int execute (void *arg);
+ // Invokes the method <action_> from the object <receiver_>.
+
+private:
+ RECEIVER &receiver_;
+ // object where the method resides.
+
+ ACTION action_;
+ // method that is going to be invoked.
+};
+
+template <class TQ, class RECEIVER, class ACTION>
+class Timer_Queue_Test_Driver
+{
+ // = TITLE
+ // Defines a class that provides a simmple implementation for
+ // a test driver for timer queues.
+ //
+ // = DESCRIPTION
+ // This is the place where the common code to test the different
+ // implementations of the timer queue resides. This class has
+ // the logic for the parse_commands() method, the run_test(),
+ // read_input() and the get_next_request(). Subclasses can
+ // override these methods if there is some logic that is specific
+ // to that implementation.
+public:
+ virtual ~Timer_Queue_Test_Driver (void);
+ // Default destructor
+
+ virtual int parse_commands (const char *buf);
+ // Breaks up the input string buffer into pieces and executes
+ // the appropriate method to handle that operation.
+
+ virtual int run_test (void);
+ // This is the main entry point to the test driver. The user
+ // of the class should normally invoke this method.
+ // Returns 0 when successful, or 0 otherwise.
+
+ virtual int get_next_request (void);
+ // This internal method gets the next request from the user.
+ // Returns -1 when user wants to exit. Returns 0 otherwise.
+
+ virtual ssize_t read_input (char *buf, size_t bufsiz);
+ // Reads input from the user into the buffer <buf> with a maximum
+ // of <bufsiz> bytes. Returns the amount of bytes actually read
+ // Otherwise, a -1 is returned and errno is set to indicate the error.
+
+ // = Template Methods.
+
+ virtual int display_menu (void)=0;
+ // Prints the user interface for the driver to STDOUT.
+
+ virtual int init (void)=0;
+ // Initializes values and operations for the driver.
+
+protected:
+ TQ timer_queue_;
+ // timer queue
+
+ // = Set of <Command>s to be executed.
+
+ Command<RECEIVER, ACTION> *schedule_cmd_;
+ // schedule timer command
+
+ Command<RECEIVER, ACTION> *cancel_cmd_;
+ // cancel timer command.
+
+ Command<RECEIVER, ACTION> *list_cmd_;
+ // list timers command.
+
+ Command<RECEIVER, ACTION> *shutdown_cmd_;
+ // shutdown the driver.
+};
+
+#if defined (ACE_TEMPLATES_REQUIRE_SOURCE)
+#include "Driver.cpp"
+#endif /* ACE_TEMPLATES_REQUIRE_SOURCE */
+
+#if defined (ACE_TEMPLATES_REQUIRE_PRAGMA)
+#pragma implementation ("Driver.cpp")
+#endif /* ACE_TEMPLATES_REQUIRE_PRAGMA */
+
+#endif /* _DRIVER_H_ */
diff --git a/ACE/examples/Timer_Queue/Makefile.am b/ACE/examples/Timer_Queue/Makefile.am
new file mode 100644
index 00000000000..e2109fde6d6
--- /dev/null
+++ b/ACE/examples/Timer_Queue/Makefile.am
@@ -0,0 +1,95 @@
+## Process this file with automake to create Makefile.in
+##
+## $Id$
+##
+## This file was generated by MPC. Any changes made directly to
+## this file will be lost the next time it is generated.
+##
+## MPC Command:
+## /acebuilds/ACE_wrappers-repository/bin/mwc.pl -include /acebuilds/MPC/config -include /acebuilds/MPC/templates -feature_file /acebuilds/ACE_wrappers-repository/local.features -noreldefs -type automake -exclude build,Kokyu
+
+ACE_BUILDDIR = $(top_builddir)
+ACE_ROOT = $(top_srcdir)
+
+## Makefile.Timer_Queue_Library.am
+
+noinst_LTLIBRARIES = libtqtd.la
+
+libtqtd_la_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR) \
+ -DACE_BUILD_SVC_DLL
+
+libtqtd_la_SOURCES = \
+ Async_Timer_Queue_Test.cpp \
+ Driver.cpp \
+ Reactor_Timer_Queue_Test.cpp \
+ Thread_Timer_Queue_Test.cpp
+
+noinst_HEADERS = \
+ Async_Timer_Queue_Test.h \
+ Driver.h \
+ Reactor_Timer_Queue_Test.h \
+ Thread_Timer_Queue_Test.h
+
+## Makefile.Timer_Queue_Async.am
+noinst_PROGRAMS = Asynch_Timer_Queue_Test
+
+Asynch_Timer_Queue_Test_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+Asynch_Timer_Queue_Test_SOURCES = \
+ main_async.cpp \
+ Async_Timer_Queue_Test.h \
+ Driver.h \
+ Reactor_Timer_Queue_Test.h \
+ Thread_Timer_Queue_Test.h
+
+Asynch_Timer_Queue_Test_LDADD = \
+ libtqtd.la \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Makefile.Timer_Queue_Reactor.am
+noinst_PROGRAMS += Reactor_Timer_Queue_Test
+
+Reactor_Timer_Queue_Test_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+Reactor_Timer_Queue_Test_SOURCES = \
+ main_reactor.cpp \
+ Async_Timer_Queue_Test.h \
+ Driver.h \
+ Reactor_Timer_Queue_Test.h \
+ Thread_Timer_Queue_Test.h
+
+Reactor_Timer_Queue_Test_LDADD = \
+ libtqtd.la \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Makefile.Timer_Queue_Thread.am
+noinst_PROGRAMS += Thread_Timer_Queue_Test
+
+Thread_Timer_Queue_Test_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+Thread_Timer_Queue_Test_SOURCES = \
+ main_thread.cpp \
+ Async_Timer_Queue_Test.h \
+ Driver.h \
+ Reactor_Timer_Queue_Test.h \
+ Thread_Timer_Queue_Test.h
+
+Thread_Timer_Queue_Test_LDADD = \
+ libtqtd.la \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Clean up template repositories, etc.
+clean-local:
+ -rm -f *~ *.bak *.rpo *.sym lib*.*_pure_* core core.*
+ -rm -f gcctemp.c gcctemp so_locations *.ics
+ -rm -rf cxx_repository ptrepository ti_files
+ -rm -rf templateregistry ir.out
+ -rm -rf ptrepository SunWS_cache Templates.DB
diff --git a/ACE/examples/Timer_Queue/README b/ACE/examples/Timer_Queue/README
new file mode 100644
index 00000000000..3cf6ec1b75b
--- /dev/null
+++ b/ACE/examples/Timer_Queue/README
@@ -0,0 +1,26 @@
+This directory contains several examples that illustrate how to use
+various concurrency mechanisms to schedule and handle timer-based
+events. All programs are interactive and utilize a common timer queue
+test framework. You can schedule or cancel time events and list all
+the timers that are waiting to be triggered.
+
+The tests include:
+
+Reactor_Timer_Queue_Test:
+-------------------------
+
+This example shows how to use ACE_Reactor as the timer queue
+management mechanism.
+
+Thread_Timer_Queue_Test:
+------------------------
+
+This example shows how to use threads as the mechanism to generate
+timer queue events.
+
+Async_Timer_Queue_Test:
+-----------------------
+
+This example shows how to use singals as the mechanism to generate
+timer queue events. It doesn't work on NT because of NT's limited
+signal mechanism, i.e., no support for SIGALRM.
diff --git a/ACE/examples/Timer_Queue/Reactor_Timer_Queue_Test.cpp b/ACE/examples/Timer_Queue/Reactor_Timer_Queue_Test.cpp
new file mode 100644
index 00000000000..c3526e8daf9
--- /dev/null
+++ b/ACE/examples/Timer_Queue/Reactor_Timer_Queue_Test.cpp
@@ -0,0 +1,223 @@
+// $Id$
+
+// ============================================================================
+// = LIBRARY
+// examples
+//
+// = FILENAME
+// Reactor_Timer_Queue_Test
+//
+// = DESCRIPTION
+// This example tests the timer queue mechanism of ACE_Reactor.
+//
+// = AUTHOR
+// Nanbor Wang <nw1@cs.wustl.edu> and
+// Sergio Flores-Gaitan <sergio@cs.wustl.edu>
+//
+// ============================================================================
+
+#include "ace/OS_NS_sys_time.h"
+#include "ace/Thread_Manager.h"
+#include "ace/Select_Reactor.h"
+#include "ace/Reactor.h"
+#include "ace/Timer_Heap.h"
+
+#include "Driver.h"
+#include "Reactor_Timer_Queue_Test.h"
+
+ACE_RCSID(Timer_Queue, Reactor_Timer_Queue_Test, "$Id$")
+
+void
+Reactor_Timer_Handler::set_timer_id (long tid)
+{
+ this->tid_ = tid;
+}
+
+int
+Reactor_Timer_Handler::handle_timeout (const ACE_Time_Value &tv,
+ const void *)
+{
+ // Macro to avoid "warning: unused parameter" type warning.
+ ACE_UNUSED_ARG (tv);
+
+ ACE_Time_Value txv = ACE_OS::gettimeofday ();
+ ACE_DEBUG ((LM_DEBUG,
+ "\nTimer #%d fired at %d.%06d (%T)!\n",
+ this->tid_,
+ txv.sec (),
+ txv.usec ()));
+ delete this;
+
+ return 0;
+}
+
+Input_Handler::Input_Handler (ACE_Timer_Queue *tq,
+ Reactor_Timer_Queue_Test_Driver &timer_queue_driver)
+ : done_ (0),
+ driver_ (timer_queue_driver)
+{
+ this->tq_ = tq;
+}
+
+int
+Input_Handler::done (void)
+{
+ return this->done_;
+}
+
+int
+Input_Handler::schedule_timer (void *argument)
+{
+ int delay = *(int *) argument;
+ Reactor_Timer_Handler *th;
+ long tid;
+
+ th = new Reactor_Timer_Handler;
+ if (th != 0)
+ {
+ tid = this->reactor ()->schedule_timer (th,
+ 0,
+ ACE_Time_Value (0, delay));
+ if (tid == -1)
+ ACE_DEBUG ((LM_DEBUG,
+ "Unable to schedule timer\n"));
+ else
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ "Timer #%d schedule to fire after %d usec from now.\n",
+ tid,
+ delay));
+ th->set_timer_id (tid);
+ }
+ }
+ else
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "not enough memory?\n"),
+ -1);
+ return tid;
+}
+
+int
+Input_Handler::cancel_timer (void *argument)
+{
+ int id = *(int *) argument;
+ return this->reactor ()->cancel_timer (id);
+}
+
+int
+Input_Handler::shutdown_timer (void *argument)
+{
+ // Macro to avoid "warning: unused parameter" type warning.
+ ACE_UNUSED_ARG (argument);
+
+ this->done_ = 1;
+ ACE_DEBUG ((LM_DEBUG,
+ "Shutting down event loop\n"));
+ return -1;
+}
+
+int
+Input_Handler::list_timer (void *argument)
+{
+ // Macro to avoid "warning: unused parameter" type warning.
+ ACE_UNUSED_ARG (argument);
+
+ ACE_Timer_Queue_Iterator &iter = this->tq_->iter ();
+ ACE_DEBUG ((LM_DEBUG,
+ "\n\nTimers in queue:\n"));
+
+ for (; !iter.isdone (); iter.next ())
+ {
+ ACE_Timer_Node *tn = iter.item ();
+ ACE_DEBUG ((LM_DEBUG, "Timer #%d: %d.%06d\n",
+ tn->get_timer_id (),
+ tn->get_timer_value ().sec (),
+ tn->get_timer_value ().usec ()));
+ }
+ return 0;
+}
+
+int
+Input_Handler::handle_input (ACE_HANDLE)
+{
+ return driver_.get_next_request ();
+}
+
+Reactor_Timer_Queue_Test_Driver::Reactor_Timer_Queue_Test_Driver (void)
+ : thandler_ (&timer_queue_, *this)
+{
+}
+
+Reactor_Timer_Queue_Test_Driver::~Reactor_Timer_Queue_Test_Driver (void)
+{
+}
+
+int
+Reactor_Timer_Queue_Test_Driver::display_menu (void)
+{
+ static char menu[] =
+ "\n*****\n"
+ "1) Schedule timer <usec>\n"
+ "2) Cancel timer <id>\n"
+ "3) List all timers\n"
+ "4) Shutdown program\n"
+ "Enter selection:";
+
+ ACE_DEBUG ((LM_DEBUG,
+ "%s",
+ menu));
+ return 0;
+}
+
+int
+Reactor_Timer_Queue_Test_Driver::init (void)
+{
+ typedef Command<Input_Handler, Input_Handler::ACTION> CMD;
+
+ // initialize <Command>s with their corresponding <Input_Handler> methods.
+ ACE_NEW_RETURN (schedule_cmd_,
+ CMD (thandler_, &Input_Handler::schedule_timer),
+ -1);
+
+ ACE_NEW_RETURN (cancel_cmd_,
+ CMD (thandler_, &Input_Handler::cancel_timer),
+ -1);
+
+ ACE_NEW_RETURN (list_cmd_,
+ CMD (thandler_, &Input_Handler::list_timer),
+ -1);
+
+ ACE_NEW_RETURN (shutdown_cmd_,
+ CMD (thandler_, &Input_Handler::shutdown_timer),
+ -1);
+
+ ACE_Reactor::instance ()->timer_queue (&timer_queue_);
+
+ ACE_Event_Handler::register_stdin_handler (&thandler_,
+ ACE_Reactor::instance (),
+ ACE_Thread_Manager::instance ());
+
+ // print the menu of options.
+ this->display_menu ();
+
+ return 0;
+}
+
+// run test was overrun due to the reactive way of handling input.
+
+int
+Reactor_Timer_Queue_Test_Driver::run_test (void)
+{
+ ACE_DEBUG ((LM_DEBUG,
+ "TIMER TEST STARTED\n"));
+
+ this->init ();
+
+ // Run until we say stop.
+ while (thandler_.done () == 0)
+ ACE_Reactor::instance ()->handle_events ();
+
+ ACE_DEBUG ((LM_DEBUG,
+ "TIMER TEST ENDED\n"));
+ return 0;
+}
diff --git a/ACE/examples/Timer_Queue/Reactor_Timer_Queue_Test.h b/ACE/examples/Timer_Queue/Reactor_Timer_Queue_Test.h
new file mode 100644
index 00000000000..3db20728814
--- /dev/null
+++ b/ACE/examples/Timer_Queue/Reactor_Timer_Queue_Test.h
@@ -0,0 +1,153 @@
+/* -*- C++ -*- */
+
+// $Id$
+
+// ============================================================================
+//
+// = LIBRARY
+// examples
+//
+// = FILENAME
+// Reactor_Timer_Queue_Test.h
+//
+// = DESCRIPTION
+// This code is an implementation of a test driver for a reactor based
+// timer queue.
+//
+// = AUTHORS
+// Nanbor Wang <nw1@cs.wustl.edu> and
+// Sergio Flores-Gaitan <sergio@cs.wustl.edu>
+//
+// ============================================================================
+
+#ifndef _REACTOR_TIMER_QUEUE_TEST_H_
+#define _REACTOR_TIMER_QUEUE_TEST_H_
+
+#include "Driver.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+/// @@todo: Not sure why this needs to be included. But am sure that,
+/// there is some circular dependency setup. Needs to be
+/// fixed. Atleast on g++
+#include "ace/Timer_Queue.h"
+#include "ace/Timer_Heap.h"
+#include "ace/svc_export.h"
+
+class Reactor_Timer_Queue_Test_Driver;
+
+class Input_Handler : public ACE_Event_Handler
+{
+ // = TITLE
+ // Implements the handler to be called for input events. Also has
+ // the logic to handle the different timer queue operations (i.e.,
+ // schedule, cancel, list, shutdown).
+ //
+ // = DESCRIPTION
+ // This class handles the reading of user input from stdin. Also
+ // has the logic to handle the commands that are to be invoked in
+ // response to the user input.
+public:
+ typedef int (Input_Handler::*ACTION) (void *);
+
+ Input_Handler (ACE_Timer_Queue *tq,
+ Reactor_Timer_Queue_Test_Driver &timer_queue_driver);
+ // Sets <done_> flag to 0, <driver_> to <timer_queue_driver> and
+ // timer queue <tq_> to <tq>
+
+ int handle_input (ACE_HANDLE);
+ // Hook method for the <ACE_Reactor> to call whenever there is input
+ // ready to be read.
+
+ int done (void);
+ // returns the value for <done_> that indicates whether we are
+ // exiting the program.A value of 0 indicates that we are NOT done,
+ // 1 otherwise.
+
+ // = Hook methods to be called from <Reactor_Timer_Queue_Test_Driver>
+
+ int schedule_timer (void *argument);
+ // Schedule a timer. The (void *) will be mapped to the delay
+ // parameter for the timer queue schedule method.
+
+ int cancel_timer (void *argument);
+ // Cancel a timer. The (void *) will be mapped to the ID of the
+ // timer being cancelled.
+
+ int list_timer (void *argument);
+ // Dump the timers in the queue. The argument is ignored.
+
+ int shutdown_timer (void *argument);
+ // Processes the request to exit the timer queue application.
+ // argument is ignored.
+
+private:
+ ACE_Timer_Queue *tq_;
+ // Keep a pointer to the timer queue we are using so we can traverse
+ // the queue.
+
+ int done_;
+ // Flag used to close down program.
+
+ Reactor_Timer_Queue_Test_Driver &driver_;
+ // Test driver. Used to call hook methods that are common code for
+ // all drivers.
+};
+
+class ACE_Svc_Export Reactor_Timer_Queue_Test_Driver : public Timer_Queue_Test_Driver <ACE_Timer_Heap, Input_Handler, Input_Handler::ACTION>
+{
+ // = TITLE
+ // Implements a test driver for a reactive timer queue using
+ // <ACE_Reactor>.
+ //
+ // = DESCRIPTION
+ // This class implements the logic to test the reactor
+ // implementation of timer queue, using an <ACE_Timer_Heap>.
+public:
+ Reactor_Timer_Queue_Test_Driver (void);
+ // Sets the input handler <thandler_> with <timer_queue_> from the
+ // <Timer_Queue_Test_Driver> class and a reference to "this", so the
+ // input handler can call hook methods from the driver. Such
+ // methods are the common factored out code from other
+ // implementations of timer queues.
+
+ virtual ~Reactor_Timer_Queue_Test_Driver (void);
+ // Default destructor
+
+ virtual int display_menu (void);
+ // Prints the menu of options.
+
+ virtual int init (void);
+ // Sets the timer queue that the REACTOR will use; registers the
+ // stdin input handler with the REACTOR and sets the <Command>s that
+ // the <Timer_Queue_Test_Driver> will execute().
+
+ virtual int run_test (void);
+ // Main entry point to the test driver implementation.
+
+private:
+ Input_Handler thandler_;
+ // This is the stdin handler.
+};
+
+class Reactor_Timer_Handler : public ACE_Event_Handler
+{
+ // = TITLE
+ // Target of the reactive timeout operation.
+public:
+ virtual int handle_timeout (const ACE_Time_Value &tv,
+ const void *);
+ // Hook method that is called by the reactor when a timer expires.
+ // It prints the timer ID and the time it expired.
+
+ void set_timer_id (long tid);
+ // Sets the timer id for this handler <tid_> to <tid>
+
+private:
+ long tid_;
+ // timer ID.
+};
+
+#endif /* _REACTOR_TIMER_QUEUE_TEST_H_ */
diff --git a/ACE/examples/Timer_Queue/Thread_Timer_Queue_Test.cpp b/ACE/examples/Timer_Queue/Thread_Timer_Queue_Test.cpp
new file mode 100644
index 00000000000..d9cf88ff5ee
--- /dev/null
+++ b/ACE/examples/Timer_Queue/Thread_Timer_Queue_Test.cpp
@@ -0,0 +1,270 @@
+// $Id$
+
+// ============================================================================
+//
+// = LIBRARY
+// examples
+//
+// = FILENAME
+// Thread_Timer_Queue_Test.cpp
+//
+// = DESCRIPTION
+// This test exercises the <ACE_Thread_Timer_Queue_Adapter>
+// using an <ACE_Timer_Heap>.
+//
+// = AUTHORS
+// Carlos O'Ryan <coryan@cs.wustl.edu> and
+// Douglas C. Schmidt <schmidt@cs.wustl.edu>
+//
+// ============================================================================
+
+#include "ace/OS_NS_stdio.h"
+#include "ace/OS_NS_sys_time.h"
+#include "ace/Task.h"
+#include "ace/Timer_Heap_T.h"
+#include "ace/Timer_Queue_Adapters.h"
+
+#include "Thread_Timer_Queue_Test.h"
+
+#include "ace/Condition_T.h"
+#include "ace/Thread_Mutex.h"
+
+ACE_RCSID(Timer_Queue, Thread_Timer_Queue_Test, "$Id$")
+
+// Administrivia methods...
+Handler::Handler(const ACE_Time_Value &expiration_time)
+ : expires_ (expiration_time),
+ id_ (0)
+{
+}
+
+Handler::~Handler (void)
+{
+}
+
+void
+Handler::set_id (int id)
+{
+ this->id_ = id;
+}
+
+// This is the method invoked when the Timer expires.
+
+int
+Handler::handle_timeout (const ACE_Time_Value &current_time,
+ const void *)
+{
+ ACE_Time_Value delay = current_time - this->expires_;
+
+ // No need to protect this printf is always called from a Async safe
+ // point.
+ ACE_OS::printf ("\nexpiring timer %d at %lu.%7.7lu secs\n"
+ "\tthere was a %lu.%7.7lu secs delay\n",
+ this->id_,
+ current_time.sec (),
+ current_time.usec (),
+ delay.sec (),
+ delay.usec ());
+ // Notice this delete is protected.
+ delete this;
+ return 0;
+}
+
+Input_Task::Input_Task (Thread_Timer_Queue *queue,
+ Thread_Timer_Queue_Test_Driver &timer_queue_driver)
+ : ACE_Task_Base (ACE_Thread_Manager::instance ()),
+ queue_ (queue),
+ usecs_ (ACE_ONE_SECOND_IN_USECS),
+ driver_ (timer_queue_driver)
+{
+}
+
+// Svc method is called from the thread library to read input from the
+// user.
+
+int
+Input_Task::svc (void)
+{
+ for (;;)
+ // call back to the driver's implementation on how to read and
+ // parse input.
+ if (this->driver_.get_next_request () == -1)
+ break;
+
+ // we are done.
+ this->queue_->deactivate ();
+ ACE_DEBUG ((LM_DEBUG,
+ "terminating input thread\n"));
+ return 0;
+}
+
+// schedule a new timer. This method will be called from inside the
+// <Timer_Queue_Test_Driver> class. (see Command pattern)
+
+int
+Input_Task::add_timer (void *argument)
+{
+ u_long useconds = *reinterpret_cast<int *> (argument);
+ ACE_Time_Value interval (useconds / usecs_,
+ useconds % usecs_);
+ ACE_Time_Value expire_at = ACE_OS::gettimeofday () + interval;
+
+ Handler *h;
+
+ ACE_NEW_RETURN (h,
+ Handler (expire_at),
+ -1);
+
+ int id = queue_->schedule (h, 0, expire_at);
+
+ if (id == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "schedule failed"),
+ -1);
+
+ // We store the id into the handler, this is only used to produce
+ // nicer messages.
+ h->set_id (id);
+
+ ACE_OS::printf ("scheduling timer %d\n",
+ id);
+ return 0;
+}
+
+// Cancel a timer. This method will be called from inside the
+// <Timer_Queue_Test_Driver> class. (see Command pattern)
+
+int
+Input_Task::cancel_timer (void *argument)
+{
+ return this->queue_->cancel (*reinterpret_cast<int *> (argument));
+}
+
+// Lists the timers in the queue. Ignores the argument. This method
+// will be called from inside the <Timer_Queue_Test_Driver> class.
+// (see Command pattern)
+
+int
+Input_Task::list_timer (void *argument)
+{
+ // Macro to avoid "warning: unused parameter" type warning.
+ ACE_UNUSED_ARG (argument);
+
+ // Dump the timer queue contents.
+ this->dump ();
+
+ return 0;
+}
+
+// Shutdown the timer queue. Return -1 indicates to the
+// <Timer_Queue_Test_Driver> class that we are done.
+
+int
+Input_Task::shutdown_timer (void *argument)
+{
+ // Macro to avoid "warning: unused parameter" type warning.
+ ACE_UNUSED_ARG (argument);
+
+#if defined (ACE_LACKS_PTHREAD_CANCEL)
+ // Cancel the thread timer queue task "voluntarily."
+ this->queue_->deactivate ();
+#else
+ // Cancel the thread timer queue task "preemptively."
+ if (ACE_Thread::cancel (this->queue_->thr_id ()) == -1)
+ ACE_ERROR ((LM_ERROR,
+ "%p\n",
+ "cancel"));
+#endif /* ACE_LACKS_PTHREAD_CANCEL */
+
+ // -1 indicates we are shutting down the application.
+ return -1;
+}
+
+void
+Input_Task::dump (void)
+{
+ ACE_GUARD (ACE_SYNCH_RECURSIVE_MUTEX, ace_mon, this->queue_->mutex ());
+
+ ACE_DEBUG ((LM_DEBUG,
+ "begin dumping timer queue\n"));
+
+ for (Timer_Heap_Iterator i (*this->queue_->timer_queue ());
+ i.item () != 0;
+ i.next ())
+ i.item ()->dump ();
+
+ ACE_DEBUG ((LM_DEBUG,
+ "end dumping timer queue\n"));
+}
+
+// constructor
+
+Thread_Timer_Queue_Test_Driver::Thread_Timer_Queue_Test_Driver (void)
+ : input_task_ (&timer_queue_, *this)
+{
+}
+
+Thread_Timer_Queue_Test_Driver::~Thread_Timer_Queue_Test_Driver (void)
+{
+}
+
+int
+Thread_Timer_Queue_Test_Driver::run_test (void)
+{
+ this->init ();
+ return 0;
+}
+
+int
+Thread_Timer_Queue_Test_Driver::display_menu (void)
+{
+ static char menu[] =
+ "Usage:\n"
+ "1 <microseconds>: setups a new timer\n"
+ "2 <timerid>: removes a timer\n"
+ "3 : prints timer queue\n"
+ "4 : exit\n";
+
+ ACE_DEBUG ((LM_DEBUG,
+ "%s",
+ menu));
+ return 0;
+}
+
+int
+Thread_Timer_Queue_Test_Driver::init (void)
+{
+ typedef Command<Input_Task, Input_Task::ACTION> CMD;
+
+ // initialize the <Command> objects with their corresponding
+ // methods from <Input_Task>
+ ACE_NEW_RETURN (schedule_cmd_,
+ CMD (input_task_, &Input_Task::add_timer),
+ -1);
+
+ ACE_NEW_RETURN (cancel_cmd_,
+ CMD (input_task_, &Input_Task::cancel_timer),
+ -1);
+
+ ACE_NEW_RETURN (list_cmd_,
+ CMD (input_task_, &Input_Task::list_timer),
+ -1);
+
+ ACE_NEW_RETURN (shutdown_cmd_,
+ CMD (input_task_, &Input_Task::shutdown_timer),
+ -1);
+
+ if (this->input_task_.activate () == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "cannot activate input task"),
+ -1);
+ else if (this->timer_queue_.activate () == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "cannot activate timer queue"),
+ -1);
+ else if (ACE_Thread_Manager::instance ()->wait () == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "wait on Thread_Manager failed"),
+ -1);
+ return 0;
+}
diff --git a/ACE/examples/Timer_Queue/Thread_Timer_Queue_Test.h b/ACE/examples/Timer_Queue/Thread_Timer_Queue_Test.h
new file mode 100644
index 00000000000..573df6121f8
--- /dev/null
+++ b/ACE/examples/Timer_Queue/Thread_Timer_Queue_Test.h
@@ -0,0 +1,157 @@
+/* -*- C++ -*- */
+
+// $Id$
+
+// ============================================================================
+//
+// = LIBRARY
+// examples
+//
+// = FILENAME
+// Thread_Timer_Queue_Test.h
+//
+// = DESCRIPTION
+// This code exercises the <ACE_Thread_Timer_Queue_Adapter> using
+// an <ACE_Timer_Heap_T>.
+//
+// = AUTHORS
+// Carlos O'Ryan <coryan@cs.wustl.edu> and
+// Sergio Flores-Gaitan <sergio@cs.wustl.edu>
+//
+// ============================================================================
+
+#ifndef _THREAD_TIMER_QUEUE_TEST_H_
+#define _THREAD_TIMER_QUEUE_TEST_H_
+
+#include "ace/Task.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/Null_Mutex.h"
+#include "ace/Timer_Heap_T.h"
+#include "ace/Timer_Queue_Adapters.h"
+#include "ace/svc_export.h"
+#include "ace/Condition_Recursive_Thread_Mutex.h"
+#include "Driver.h"
+
+// These typedefs ensure that we use the minimal amount of locking
+// necessary.
+typedef ACE_Event_Handler_Handle_Timeout_Upcall<ACE_Null_Mutex>
+ Upcall;
+typedef ACE_Timer_Heap_T<ACE_Event_Handler *,
+ Upcall,
+ ACE_Null_Mutex>
+ Timer_Heap;
+typedef ACE_Timer_Heap_Iterator_T<ACE_Event_Handler *,
+ Upcall,
+ ACE_Null_Mutex>
+ Timer_Heap_Iterator;
+typedef ACE_Thread_Timer_Queue_Adapter<Timer_Heap>
+ Thread_Timer_Queue;
+
+// Forward declaration.
+class Thread_Timer_Queue_Test_Driver;
+
+class Input_Task : public ACE_Task_Base
+{
+ // = TITLE
+ // Read user actions on the Timer_Queue from stdin.
+ //
+ // = DESCRIPTION
+ // This class reads user input from stdin; those commands permit
+ // the control of a Timer_Queue, which is dispatched by another
+ // thread.
+public:
+ typedef int (Input_Task::*ACTION) (void *);
+
+ Input_Task (Thread_Timer_Queue *queue,
+ Thread_Timer_Queue_Test_Driver &timer_queue_driver);
+
+ virtual int svc (void);
+ // This method runs the event loop in the new thread.
+
+ // = Some helper methods.
+
+ int add_timer (void *);
+ // Add a new timer to expire in <seconds> more.
+
+ int cancel_timer (void *);
+ // Cancel timer <id>.
+
+ int list_timer (void *);
+ // List the current scheduled timers.
+
+ int shutdown_timer (void *);
+ // Shutdown task.
+
+ void dump (void);
+ // Dump the state of the timer queue.
+
+private:
+ Thread_Timer_Queue *queue_;
+ // The timer queue implementation.
+
+ const int usecs_;
+ // How many micro seconds are in a second.
+
+ Thread_Timer_Queue_Test_Driver &driver_;
+ // The thread timer queue test driver.
+};
+
+class ACE_Svc_Export Thread_Timer_Queue_Test_Driver : public Timer_Queue_Test_Driver <Thread_Timer_Queue, Input_Task, Input_Task::ACTION>
+{
+ // = TITLE
+ // Implements an example application that exercises
+ // <Thread_Timer_Queue> timer queue.
+ //
+ // = DESCRIPTION
+ // This class implements a simple test driver for the
+ // <Thread_Timer_Queue>. The <display_menu> hook method is
+ // called from the base class to print a menu specific to the
+ // thread implementation of the timer queue.
+public:
+ Thread_Timer_Queue_Test_Driver (void);
+ ~Thread_Timer_Queue_Test_Driver (void);
+
+ virtual int display_menu (void);
+ virtual int init (void);
+ virtual int run_test (void);
+
+private:
+ Input_Task input_task_;
+ // Subclassed from ACE_Task.
+};
+
+class Handler : public ACE_Event_Handler
+{
+ // = TITLE
+ // Event handler for the timer queue timeout events.
+ //
+ // = DESCRIPTION
+ // The <handle_timeout> hook method prints out the current time,
+ // prints the time when this timer expired and deletes "this".
+public:
+ Handler (const ACE_Time_Value &expiration_time);
+ ~Handler (void);
+
+ void set_id (int id);
+ // Store an "id" for the Handler, which is only use to print better
+ // messages.
+
+ virtual int handle_timeout (const ACE_Time_Value &current_time,
+ const void *arg);
+ // Call back hook.
+
+private:
+ ACE_Time_Value expires_;
+ // Store the expected time of expiration, it is used to print a nice
+ // message saying how much delay was at the actual expiration time.
+
+ int id_;
+ // Store an "id" for the Handler, which is only use to print better
+ // messages.
+};
+
+#endif /* _THREAD_TIMER_QUEUE_TEST_H_ */
diff --git a/ACE/examples/Timer_Queue/Timer_Queue.mpc b/ACE/examples/Timer_Queue/Timer_Queue.mpc
new file mode 100644
index 00000000000..04026c0babd
--- /dev/null
+++ b/ACE/examples/Timer_Queue/Timer_Queue.mpc
@@ -0,0 +1,40 @@
+// -*- MPC -*-
+// $Id$
+
+project(*Library) : acelib {
+ sharedname = tqtd
+ dynamicflags += ACE_BUILD_SVC_DLL
+ Source_Files {
+ Async_Timer_Queue_Test.cpp
+ Driver.cpp
+ Reactor_Timer_Queue_Test.cpp
+ Thread_Timer_Queue_Test.cpp
+ }
+}
+
+project(*Async) : aceexe {
+ exename = Asynch_Timer_Queue_Test
+ after += Timer_Queue_Library
+ libs += tqtd
+ Source_Files {
+ main_async.cpp
+ }
+}
+
+project(*Reactor) : aceexe {
+ exename = Reactor_Timer_Queue_Test
+ after += Timer_Queue_Library
+ libs += tqtd
+ Source_Files {
+ main_reactor.cpp
+ }
+}
+
+project(*Thread) : aceexe {
+ exename = Thread_Timer_Queue_Test
+ after += Timer_Queue_Library
+ libs += tqtd
+ Source_Files {
+ main_thread.cpp
+ }
+}
diff --git a/ACE/examples/Timer_Queue/main_async.cpp b/ACE/examples/Timer_Queue/main_async.cpp
new file mode 100644
index 00000000000..8c21c4fcdd2
--- /dev/null
+++ b/ACE/examples/Timer_Queue/main_async.cpp
@@ -0,0 +1,57 @@
+// $Id$
+
+// ============================================================================
+//
+// = LIBRARY
+// examples
+//
+// = FILENAME
+// main_async.cpp
+//
+// = DESCRIPTION
+// Implements an asynchronous timer queue.
+// This code exercises the Timer_Queue_Test_Driver class using
+// signals as an asynchronous mechanism to dispatch events.
+//
+// = AUTHORS
+// Douglas Schmidt <schmidt@cs.wustl.edu> &&
+// Sergio Flores-Gaitan <sergio@cs.wustl.edu>
+//
+// ============================================================================
+
+// The following #pragma is needed to disable a warning that occurs
+// in MSVC 6 due to the overly long debugging symbols generated for
+// the std::auto_ptr<Timer_Queue_Test_Driver<...> > template
+// instance used by some of the methods in this file.
+#ifdef _MSC_VER
+# pragma warning(disable: 4786) /* identifier was truncated to '255'
+ characters in the browser
+ information */
+#endif /* _MSC_VER */
+
+#include "ace/OS_main.h"
+#include "ace/Auto_Ptr.h"
+#include "Driver.h"
+#include "Async_Timer_Queue_Test.h"
+
+ACE_RCSID (Timer_Queue,
+ main_async,
+ "$Id$")
+
+typedef Timer_Queue_Test_Driver<Async_Timer_Queue *,
+ Async_Timer_Queue,
+ Async_Timer_Queue::ACTION>
+ ASYNC_TIMER_QUEUE_TEST_DRIVER;
+
+int
+ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ ASYNC_TIMER_QUEUE_TEST_DRIVER *tqtd;
+ ACE_NEW_RETURN (tqtd, Async_Timer_Queue_Test_Driver, -1);
+ // Auto ptr ensures that the driver memory is released
+ // automatically.
+ auto_ptr <ASYNC_TIMER_QUEUE_TEST_DRIVER> driver (tqtd);
+
+ return driver->run_test ();
+}
+
diff --git a/ACE/examples/Timer_Queue/main_reactor.cpp b/ACE/examples/Timer_Queue/main_reactor.cpp
new file mode 100644
index 00000000000..9ce80093bd9
--- /dev/null
+++ b/ACE/examples/Timer_Queue/main_reactor.cpp
@@ -0,0 +1,57 @@
+// $Id$
+
+// ============================================================================
+//
+// = LIBRARY
+// examples
+//
+// = FILENAME
+// main_reactor.cpp
+//
+// = DESCRIPTION
+// Implements an reactive timer queue.
+// This code exercises the Timer_Queue_Test_Driver class using
+// a reactor.
+//
+// = AUTHORS
+// Douglas Schmidt <schmidt@cs.wustl.edu> &&
+// Sergio Flores-Gaitan <sergio@cs.wustl.edu>
+//
+// ============================================================================
+
+// The following #pragma is needed to disable a warning that occurs
+// in MSVC 6 due to the overly long debugging symbols generated for
+// the std::auto_ptr<Timer_Queue_Test_Driver<...> > template
+// instance used by some of the methods in this file.
+#ifdef _MSC_VER
+# pragma warning(disable: 4786) /* identifier was truncated to '255'
+ characters in the browser
+ information */
+#endif /* _MSC_VER */
+
+#include "ace/OS_main.h"
+#include "ace/Auto_Ptr.h"
+#include "Reactor_Timer_Queue_Test.h"
+#include "Driver.h"
+
+ACE_RCSID (Timer_Queue,
+ main_reactor,
+ "$Id$")
+
+typedef Timer_Queue_Test_Driver <ACE_Timer_Heap,
+ Input_Handler,
+ Input_Handler::ACTION>
+ REACTOR_TIMER_QUEUE_TEST_DRIVER;
+
+int
+ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ REACTOR_TIMER_QUEUE_TEST_DRIVER *tqtd;
+ ACE_NEW_RETURN (tqtd, Reactor_Timer_Queue_Test_Driver, -1);
+ // Auto ptr ensures that the driver memory is released
+ // automatically.
+ auto_ptr <REACTOR_TIMER_QUEUE_TEST_DRIVER> driver (tqtd);
+
+ return driver->run_test ();
+}
+
diff --git a/ACE/examples/Timer_Queue/main_thread.cpp b/ACE/examples/Timer_Queue/main_thread.cpp
new file mode 100644
index 00000000000..7287e0ed263
--- /dev/null
+++ b/ACE/examples/Timer_Queue/main_thread.cpp
@@ -0,0 +1,58 @@
+// $Id$
+
+// ============================================================================
+//
+// = LIBRARY
+// examples
+//
+// = FILENAME
+// main_thread.cpp
+//
+// = DESCRIPTION
+// Implements an threaded timer queue.
+// This code exercises the Timer_Queue_Test_Driver class using
+// threads.
+//
+// = AUTHORS
+// Douglas Schmidt <schmidt@cs.wustl.edu> &&
+// Sergio Flores-Gaitan <sergio@cs.wustl.edu>
+//
+// ============================================================================
+
+// The following #pragma is needed to disable a warning that occurs
+// in MSVC 6 due to the overly long debugging symbols generated for
+// the std::auto_ptr<Timer_Queue_Test_Driver<...> > template
+// instance used by some of the methods in this file.
+#ifdef _MSC_VER
+# pragma warning(disable: 4786) /* identifier was truncated to '255'
+ characters in the browser
+ information */
+#endif /* _MSC_VER */
+
+#include "ace/OS_main.h"
+#include "ace/Auto_Ptr.h"
+#include "Driver.h"
+#include "Thread_Timer_Queue_Test.h"
+
+ACE_RCSID (Timer_Queue,
+ main_thread,
+ "$Id$")
+
+typedef Timer_Queue_Test_Driver<Thread_Timer_Queue,
+ Input_Task,
+ Input_Task::ACTION>
+ THREAD_TIMER_QUEUE_TEST_DRIVER;
+
+int
+ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ // Auto ptr ensures that the driver memory is released
+ // automatically.
+ THREAD_TIMER_QUEUE_TEST_DRIVER *tqtd;
+ ACE_NEW_RETURN (tqtd, Thread_Timer_Queue_Test_Driver, -1);
+
+ auto_ptr <THREAD_TIMER_QUEUE_TEST_DRIVER> driver (tqtd);
+
+ return driver->run_test ();
+}
+
diff --git a/ACE/examples/Web_Crawler/.cvsignore b/ACE/examples/Web_Crawler/.cvsignore
new file mode 100644
index 00000000000..ba2906d0666
--- /dev/null
+++ b/ACE/examples/Web_Crawler/.cvsignore
@@ -0,0 +1 @@
+main
diff --git a/ACE/examples/Web_Crawler/Command_Processor.cpp b/ACE/examples/Web_Crawler/Command_Processor.cpp
new file mode 100644
index 00000000000..83289095444
--- /dev/null
+++ b/ACE/examples/Web_Crawler/Command_Processor.cpp
@@ -0,0 +1,128 @@
+// $Id$
+
+#include "ace/OS_NS_string.h"
+#include "URL.h"
+#include "HTTP_URL.h"
+#include "Options.h"
+#include "Command_Processor.h"
+#include "URL_Visitor.h"
+
+ACE_RCSID(Web_Crawler, Command_Processor, "$Id$")
+
+Command::~Command (void)
+{
+}
+
+URL_Command::URL_Command (URL *url)
+ : url_ (url)
+{
+}
+
+int
+URL_Command::execute (void)
+{
+
+ ACE_CString check_string
+ (ACE_TEXT_ALWAYS_CHAR (this->url_->url_addr ().get_path_name ()));
+ if (check_string.find ("news:") != ACE_CString::npos)
+ return 0;
+
+ if (check_string.find (".cgi") != ACE_CString::npos)
+ return 0;
+
+ if (check_string.find ("mailto") != ACE_CString::npos)
+ return 0;
+
+ if (check_string.find (".gif") != ACE_CString::npos)
+ return 0;
+
+ if (check_string.find (".pdf") != ACE_CString::npos)
+ return 0;
+
+ if (check_string.find (".map") != ACE_CString::npos)
+ return 0;
+
+ if (check_string.find (".bmp") != ACE_CString::npos)
+ return 0;
+
+ if (check_string.find (".jpg") != ACE_CString::npos)
+ return 0;
+
+ if (this->url_->accept (OPTIONS::instance ()->visitor ()) !=0)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ "Coudnt accept url\n"));
+ return -1;
+ }
+ return 0;
+}
+
+int
+URL_Command::destroy (void)
+{
+ delete this;
+ return 0;
+}
+Command_Processor::Command_Processor (void)
+{
+}
+
+Command_Processor::~Command_Processor (void)
+{
+}
+
+int
+Command_Processor::destroy (void)
+{
+ delete this;
+ return 0;
+return 0;
+}
+
+int
+Command_Processor::execute (void)
+{
+ Command *command;
+ while (this->url_queue_.is_empty () != 1)
+ {
+ if (this->url_queue_.dequeue_head (command) != 0)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%p\n", "dequeue_head"),
+ -1);
+ URL_Command *url_command = dynamic_cast<URL_Command *> (command);
+ Auto_Destroyer<URL_Command> url_command_ptr (url_command);
+ if (url_command_ptr->execute () != 0)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%p\n", "Couldnt execute command"),
+ -1);
+ }
+ return 0;
+}
+
+int
+Command_Processor::insert (Command *command)
+{
+ // According to the order specified the commands are removed from the queue.
+ if (this->url_queue_.is_full() != 1)
+ {
+ if (ACE_OS::strcmp (OPTIONS::instance ()->order (), ACE_TEXT ("FIFO")) == 0)
+ {
+ if (this->url_queue_.enqueue_tail (command) !=0)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"), ACE_TEXT ("enqueue_tail")),
+ - 1);
+ }
+ if (ACE_OS::strcmp (OPTIONS::instance ()->order (), ACE_TEXT ("LIFO")) == 0)
+ {
+ if (this->url_queue_.enqueue_head (command) !=0)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"), ACE_TEXT ("enqueue_head")),
+ - 1);
+ }
+ }
+ return 0;
+}
+
+#if defined (ACE_HAS_EXPLICIT_STATIC_TEMPLATE_MEMBER_INSTANTIATION)
+template ACE_Singleton<Options, ACE_Null_Mutex> *ACE_Singleton<Options, ACE_Null_Mutex>::singleton_;
+#endif /* ACE_HAS_EXPLICIT_STATIC_TEMPLATE_MEMBER_INSTANTIATION */
diff --git a/ACE/examples/Web_Crawler/Command_Processor.h b/ACE/examples/Web_Crawler/Command_Processor.h
new file mode 100644
index 00000000000..742a316804c
--- /dev/null
+++ b/ACE/examples/Web_Crawler/Command_Processor.h
@@ -0,0 +1,98 @@
+/* -*- C++ -*- */
+// $Id$
+
+// ============================================================================
+//
+// = LIBRARY
+// examples/Web_Crawler
+//
+// = FILENAME
+// Command_Processor.h
+//
+// = AUTHOR
+// Douglas C. Schmidt <schmidt@cs.wustl.edu>
+//
+// ============================================================================
+
+#ifndef _COMMAND_PROCESSOR_H
+#define _COMMAND_PROCESSOR_H
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+#pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/Containers.h"
+#include "Options.h"
+
+// Forward decl.
+class URL;
+
+class Command
+{
+ // = TITLE
+ // Abstract base class for a command.
+ //
+ // = DESCRIPTION
+ // Each command is executed by a <Command_Processor>.
+public:
+ virtual ~Command (void);
+ // Virtual destructor.
+
+ virtual int execute (void) = 0;
+ // This is the entry point to execute the command.
+ virtual int destroy (void) = 0;
+};
+
+class URL_Command : public Command
+{
+ // = TITLE
+ // Defines an API for executing a command on a URL.
+ //
+ // = DESCRIPTION
+ // Each command is executed by a <Command_Processor>.
+public:
+ URL_Command (URL *);
+ // Constructor.
+
+ virtual int execute (void);
+ // Execute the URL command.
+
+ int destroy (void);
+ // Commit suicide.
+private:
+ URL *url_;
+ // Pointer to the URL.
+};
+
+class Command_Processor
+{
+ // = TITLE
+ // Execute commands that are passed to it.
+ //
+ // = DESCRIPTION
+ // This class implements the Command Processor pattern.
+public:
+ Command_Processor (void);
+
+ int insert (Command *);
+ // Insert a new <Command> into the <Command_Processor>'s queue.
+
+ int execute (void);
+ // Execute all the <Commands> in the queue.
+
+ int destroy (void);
+ // Destroy the <Command_Processor>.
+
+private:
+ friend class ACE_Shutup_GPlusPlus;
+ // Turn off g++ warning
+
+ ~Command_Processor (void);
+ // Ensure dynamic allocation.
+
+ // @@ You fill in here...
+ ACE_Unbounded_Queue<Command *> url_queue_;
+};
+
+
+#endif /* _COMMAND_PROCESSOR_H */
diff --git a/ACE/examples/Web_Crawler/HTTP_URL.cpp b/ACE/examples/Web_Crawler/HTTP_URL.cpp
new file mode 100644
index 00000000000..44ceea324d4
--- /dev/null
+++ b/ACE/examples/Web_Crawler/HTTP_URL.cpp
@@ -0,0 +1,87 @@
+// $Id$
+
+#include "ace/OS_NS_stdio.h"
+#include "ace/OS_NS_string.h"
+#include "ace/Auto_Ptr.h"
+#include "URL_Visitor.h"
+#include "Options.h"
+#include "HTTP_URL.h"
+
+ACE_RCSID(Web_Crawler, HTTP_URL, "$Id$")
+
+const ACE_URL_Addr &
+HTTP_URL::url_addr (void) const
+{
+ return this->url_addr_;
+}
+
+HTTP_URL::HTTP_URL (const ACE_URL_Addr &url_addr,
+ HTTP_URL *cp)
+ : url_addr_ (url_addr),
+ containing_page_ (cp == 0 ? this : cp)
+{
+ ACE_DEBUG ((LM_DEBUG, "HTTP_URL %s\n", url_addr.addr_to_string ()));
+}
+
+ssize_t
+HTTP_URL::send_request (void)
+{
+ size_t commandsize =
+ ACE_OS::strlen (this->url_addr ().get_path_name ())
+ + ACE_OS::strlen (this->url_addr ().get_host_name ())
+ + 20 // Extra
+ + 1 // NUL byte
+ + 16; // Protocol filler...
+
+ char *command;
+ ACE_NEW_RETURN (command,
+ char[commandsize],
+ -1);
+
+ // Ensure that the <command> memory is deallocated.
+ ACE_Auto_Basic_Array_Ptr<char> cmd_ptr (command);
+
+ ACE_OS::sprintf (cmd_ptr.get (),
+ "GET /%s HTTP/1.1\r\n",
+ ACE_TEXT_ALWAYS_CHAR (this->url_addr ().get_path_name ()));
+
+ // Send the GET command to the connected server.
+ if (this->stream ().send_n (cmd_ptr.get (),
+ ACE_OS::strlen (cmd_ptr.get ()),
+ const_cast<ACE_Time_Value *>
+ (OPTIONS::instance ()->timeout ())) > 0)
+ {
+ ACE_OS::sprintf (cmd_ptr.get (),
+ "Host: %s\r\n\r\n",
+ this->url_addr ().get_host_name ());
+
+ // IMP: The length of teh command has to be sent!
+ ssize_t retval =
+ this->stream ().send_n (cmd_ptr.get (),
+ ACE_OS::strlen (cmd_ptr.get ()),
+ const_cast<ACE_Time_Value *>
+ (OPTIONS::instance ()->timeout ()));
+ this->stream ().svc_handler ()->idle (0);
+ if (retval <= 0)
+ return -1;
+ else
+ return retval;
+ }
+ else
+ return -1;
+}
+
+int
+HTTP_URL::accept (URL_Visitor *visitor)
+{
+ // This is part of the visitor pattern.
+ return visitor->visit (*this);
+}
+
+int
+HTTP_URL::destroy (void)
+{
+ delete this;
+ return 0;
+ // Commit suicide!
+}
diff --git a/ACE/examples/Web_Crawler/HTTP_URL.h b/ACE/examples/Web_Crawler/HTTP_URL.h
new file mode 100644
index 00000000000..a926bb47938
--- /dev/null
+++ b/ACE/examples/Web_Crawler/HTTP_URL.h
@@ -0,0 +1,64 @@
+/* -*- C++ -*- */
+// $Id$
+
+// ============================================================================
+//
+// = LIBRARY
+// examples/Web_Crawler
+//
+// = FILENAME
+// HTTP_URL.h
+//
+// = AUTHOR
+// Douglas C. Schmidt <schmidt@cs.wustl.edu>
+//
+// ============================================================================
+
+#ifndef _HTTP_URL_H
+#define _HTTP_URL_H
+
+#include "URL_Status.h"
+#include "URL.h"
+#include "Options.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+#pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+class HTTP_URL : public URL
+{
+ // = TITLE
+ // An ADT for an HTTP URL.
+ //
+ // = DESCRIPTION
+ // This class plays the "element" role in the Visitor pattern.
+public:
+ HTTP_URL (const ACE_URL_Addr &url_addr,
+ HTTP_URL *containing_page = 0);
+ // The <url_addr> is the URL that we're going to be visiting. We
+ // also keep track of the containing page, if any, which is used to
+ // print out more meaningful messages.
+
+ virtual int accept (URL_Visitor *visitor);
+ // Accept the visitor, which will then perform a particular
+ // visitation strategy on the URL. This method is part of the
+ // Visitor pattern.
+
+ virtual ssize_t send_request (void);
+ // Send a <GET> command to fetch the contents in the URI from the
+ // server.
+
+ virtual const ACE_URL_Addr &url_addr (void) const;
+ // Returns the URL that we represent.
+
+ int destroy (void);
+ // Commit suicide
+private:
+ ACE_URL_Addr url_addr_;
+ // Address of the URL we're connected to.
+
+ HTTP_URL *containing_page_;
+ // Page that contained us.
+};
+
+#endif /* _HTTP_URL_H */
diff --git a/ACE/examples/Web_Crawler/Iterators.cpp b/ACE/examples/Web_Crawler/Iterators.cpp
new file mode 100644
index 00000000000..98b4f999622
--- /dev/null
+++ b/ACE/examples/Web_Crawler/Iterators.cpp
@@ -0,0 +1,163 @@
+// $Id$
+
+#include "Options.h"
+#include "Iterators.h"
+
+ACE_RCSID(Web_Crawler, Iterators, "$Id$")
+
+URL_Iterator::~URL_Iterator (void)
+{
+}
+
+int
+URL_Iterator::destroy (void)
+{
+ // Commit suicide.
+ delete this;
+ return 0;
+}
+
+HTML_Body_Iterator::HTML_Body_Iterator (URL &url)
+ : url_ (url)
+{
+}
+
+int
+HTML_Body_Iterator::next (ACE_CString &url)
+{
+ size_t len = BUFSIZ;
+ const char *buf;
+ ACE_CString buffer;
+ int href_index = 0;
+
+ for (buf = this->url_.stream ().recv (len);
+ buf > 0;
+ buf = this->url_.stream ().recv (len))
+ {
+
+ buffer.set (buf, BUFSIZ, 1);
+
+ href_index = buffer.find ("HREF");
+
+ if (href_index < 0)
+ href_index = buffer.find ("href");
+
+ // Grep fpr " and grab the string until end-"
+ if ( href_index > 0)
+ {
+ // Get back to buffer start location.
+ this->url_.stream ().seek (-1 * static_cast<off_t> (len),
+ SEEK_CUR);
+
+ int start_index = buffer.find ('\"',
+ href_index);
+ if (start_index <= 0)
+ break;
+
+ start_index += href_index;
+
+ int end_index = buffer.find ('\"',
+ start_index + 1);
+ if (end_index <= 0)
+ break;
+
+ end_index += start_index + 1;
+
+ ssize_t url_len = end_index - (start_index + 1);
+
+ ACE_CString temp = buffer.substring (start_index + 1,
+ url_len);
+ url.set (temp.c_str (), len, 1);
+
+ this->url_.stream ().seek (end_index + 1);
+
+ return url_len;
+ }
+ }
+ return 0;
+
+}
+
+HTTP_Header_Iterator::HTTP_Header_Iterator (URL &url)
+ : url_ (url),
+ end_of_header_ (0)
+{
+}
+
+int
+HTTP_Header_Iterator::next (ACE_CString &line)
+{
+ if (this->end_of_header_)
+ return 0;
+ else
+ {
+ for (char c;
+ (c = this->url_.stream ().get_char ()) != (char)EOF;
+ )
+ {
+ // Check to see if we're at the end of the header line.
+ if (c == '\r' && this->url_.stream ().peek_char (0) == '\n')
+ {
+ line.set (this->url_.stream ().recv (),
+ this->url_.stream ().recv_len () - 1,
+ 1);
+
+ // Check to see if we're at the end of the header.
+ if (this->url_.stream ().peek_char (1) == '\r'
+ && this->url_.stream ().peek_char (2) == '\n')
+ {
+ this->end_of_header_ = 1;
+ // We're at the end of the header section.
+ this->url_.stream ().seek (3);
+ }
+ else
+ // We're at the end of the line.
+ this->url_.stream ().seek (1);
+
+ return 1;
+ }
+ // Handle broken Web servers that use '\n' instead of
+ // '\r\n'.
+ else if (c == '\n')
+ {
+ line.set (this->url_.stream ().recv (),
+ (this->url_.stream ().recv_len ()),
+ 1);
+
+ // Check to see if we're at the end of the header.
+ if (this->url_.stream ().peek_char (0) == '\n')
+ {
+ // We're at the end of the header section.
+ this->url_.stream ().seek (1);
+ this->end_of_header_ = 1;
+ }
+
+ return 1;
+ }
+ }
+
+ }
+ return 0;
+}
+
+URL_Download_Iterator::URL_Download_Iterator (URL &url)
+ : url_ (url)
+{
+}
+
+int
+URL_Download_Iterator::next (ACE_CString &buffer)
+{
+ size_t len = BUFSIZ;
+
+ const char *buf = this->url_.stream ().recv (len);
+
+
+ if (buf == 0)
+ return 0;
+ else
+ {
+ buffer.set (buf, len, 1);
+ return 1;
+ }
+}
diff --git a/ACE/examples/Web_Crawler/Iterators.h b/ACE/examples/Web_Crawler/Iterators.h
new file mode 100644
index 00000000000..b5d267f7afb
--- /dev/null
+++ b/ACE/examples/Web_Crawler/Iterators.h
@@ -0,0 +1,117 @@
+/* -*- C++ -*- */
+// $Id$
+
+// ============================================================================
+//
+// = LIBRARY
+// examples/Web_Crawler
+//
+// = FILENAME
+// Iterators.h
+//
+// = AUTHOR
+// Douglas C. Schmidt <schmidt@cs.wustl.edu>
+//
+// ============================================================================
+
+#ifndef _ITERATORS_H
+#define _ITERATORS_H
+
+#include "URL.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+#pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+class URL_Iterator
+{
+ // = TITLE
+ // An abstract base class that defines an iterator.
+ //
+ // = DESCRIPTION
+ // Subclasses of this base class can define what strings
+ // to return from <next>. This class decouples higher-level
+ // software from the details of whatever type of URL header or
+ // body we're iterating over.
+public:
+ // = Initialization and termination methods.
+ virtual int destroy (void);
+ // "virtual" destructor.
+
+ // = Iterator methods.
+ virtual int next (ACE_CString &string) = 0;
+ // Pass back the next <string> that hasn't been seen yet. Returns 0
+ // when all items have been seen, else 1.
+
+protected:
+ virtual ~URL_Iterator (void);
+ // C++ destructor.
+};
+
+class HTML_Body_Iterator : public URL_Iterator
+{
+ // = TITLE
+ // An iterator that returns URLs embedded in HTML files.
+public:
+ // = Initialization and termination methods.
+ HTML_Body_Iterator (URL &url);
+ // Constructor.
+
+ // = Iterator methods.
+ virtual int next (ACE_CString &url);
+ // Pass back the next <url> that hasn't been seen in the
+ // memory-mapped file. Returns 0 when all items have been seen,
+ // else 1.
+
+private:
+ URL &url_;
+ // HTTP URL that we're iterating over.
+};
+
+class HTTP_Header_Iterator : public URL_Iterator
+{
+ // = TITLE
+ // An iterator that iterates over the HTTP header.
+public:
+ // = Initialization and termination methods.
+ HTTP_Header_Iterator (URL &url);
+ // Constructor.
+
+ // = Iterator methods.
+ virtual int next (ACE_CString &line);
+ // Pass back the next <line> that hasn't been seen in the
+ // memory-mapped file header. Returns 0 when we've reached the end
+ // of the header. seen, else 1.
+
+private:
+ URL &url_;
+ // HTTP URL that we're iterating over.
+
+ int end_of_header_;
+ // We've found the end of the header, which means this iterator is
+ // finished.
+};
+
+class URL_Download_Iterator : public URL_Iterator
+{
+ // = TITLE
+ // An iterator that iterates over the contents of an entire URL,
+ // i.e., both header and body, and returns it in <BUFSIZ>
+ // <buffer>s.
+public:
+ // = Initialization and termination methods.
+ URL_Download_Iterator (URL &url);
+ // Constructor.
+
+ // = Iterator methods.
+ virtual int next (ACE_CString &buffer);
+ // Pass back the next <buffer> data from the stream, where
+ // <buffer.size> <= <BUFSIZ> . Returns 0 when we've reached the end
+ // of the header, else 1.
+
+private:
+ URL &url_;
+ // HTTP URL that we're iterating over.
+};
+
+#endif /* _ITERATORS_H */
diff --git a/ACE/examples/Web_Crawler/Makefile.am b/ACE/examples/Web_Crawler/Makefile.am
new file mode 100644
index 00000000000..00a30a4d2e1
--- /dev/null
+++ b/ACE/examples/Web_Crawler/Makefile.am
@@ -0,0 +1,60 @@
+## Process this file with automake to create Makefile.in
+##
+## $Id$
+##
+## This file was generated by MPC. Any changes made directly to
+## this file will be lost the next time it is generated.
+##
+## MPC Command:
+## /acebuilds/ACE_wrappers-repository/bin/mwc.pl -include /acebuilds/MPC/config -include /acebuilds/MPC/templates -feature_file /acebuilds/ACE_wrappers-repository/local.features -noreldefs -type automake -exclude build,Kokyu
+
+ACE_BUILDDIR = $(top_builddir)
+ACE_ROOT = $(top_srcdir)
+
+
+## Makefile.Web_Crawler.am
+
+if !BUILD_ACE_FOR_TAO
+noinst_PROGRAMS = main
+
+main_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+main_SOURCES = \
+ Command_Processor.cpp \
+ HTTP_URL.cpp \
+ Iterators.cpp \
+ Mem_Map_Stream.cpp \
+ Options.cpp \
+ URL.cpp \
+ URL_Addr.cpp \
+ URL_Status.cpp \
+ URL_Visitor.cpp \
+ URL_Visitor_Factory.cpp \
+ Web_Crawler.cpp \
+ main.cpp \
+ Command_Processor.h \
+ HTTP_URL.h \
+ Iterators.h \
+ Mem_Map_Stream.h \
+ Options.h \
+ URL.h \
+ URL_Addr.h \
+ URL_Status.h \
+ URL_Visitor.h \
+ URL_Visitor_Factory.h \
+ Web_Crawler.h
+
+main_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+endif !BUILD_ACE_FOR_TAO
+
+## Clean up template repositories, etc.
+clean-local:
+ -rm -f *~ *.bak *.rpo *.sym lib*.*_pure_* core core.*
+ -rm -f gcctemp.c gcctemp so_locations *.ics
+ -rm -rf cxx_repository ptrepository ti_files
+ -rm -rf templateregistry ir.out
+ -rm -rf ptrepository SunWS_cache Templates.DB
diff --git a/ACE/examples/Web_Crawler/Mem_Map_Stream.cpp b/ACE/examples/Web_Crawler/Mem_Map_Stream.cpp
new file mode 100644
index 00000000000..dda1d465a71
--- /dev/null
+++ b/ACE/examples/Web_Crawler/Mem_Map_Stream.cpp
@@ -0,0 +1,240 @@
+// $Id$
+
+#include "ace/FILE_Addr.h"
+#include "ace/Auto_Ptr.h"
+#include "Options.h"
+#include "Mem_Map_Stream.h"
+
+ACE_RCSID(Web_Crawler, Mem_Map_Stream, "$Id$")
+
+ACE_SOCK_Stream &
+Mem_Map_Stream::stream (void)
+{
+ return svc_handler_->peer ();
+}
+
+ssize_t
+Mem_Map_Stream::send_n (const void *buf, size_t size, ACE_Time_Value *tv)
+{
+ return svc_handler_->peer ().send_n (buf, size, 0, tv);
+}
+
+int
+Mem_Map_Stream::eof (void) const
+{
+ return this->get_pos_ >= this->end_of_mapping_plus1_;
+}
+
+int
+Mem_Map_Stream::get_char (void)
+{
+ if (this->eof () && this->grow_file_and_remap () == -1)
+ return EOF;
+
+ return *this->get_pos_++;
+}
+
+int
+Mem_Map_Stream::rewind (void)
+{
+ this->recv_pos_ =
+ reinterpret_cast<char *> (this->mem_map_.addr ());
+ this->get_pos_ = this->recv_pos_;
+ this->end_of_mapping_plus1_ =
+ this->recv_pos_ + this->mem_map_.size ();
+ return 0;
+}
+
+int
+Mem_Map_Stream::peek_char (size_t offset)
+{
+ // We may need to iterate if the size of <n> is large.
+ while (this->get_pos_ + offset >= this->end_of_mapping_plus1_)
+ if (this->grow_file_and_remap () == -1)
+ return EOF;
+
+ return this->get_pos_[offset];
+}
+
+const char *
+Mem_Map_Stream::recv (void) const
+{
+ return this->recv_pos_;
+}
+
+const char *
+Mem_Map_Stream::recv (size_t &len)
+{
+ if (this->eof () && this->grow_file_and_remap () == -1)
+ return 0;
+
+
+ const char *s = this->recv_pos_;
+ off_t olen = static_cast <off_t> (len);
+ this->seek (olen, SEEK_CUR);
+ len = this->get_pos_ - s;
+ return s;
+}
+
+size_t
+Mem_Map_Stream::recv_len (void) const
+{
+ return this->get_pos_ - this->recv_pos_;
+}
+
+const char *
+Mem_Map_Stream::peek_str (size_t offset,
+ size_t size)
+{
+ // We will iterate if the size of <offset> is large.
+ while (this->get_pos_ + (offset + size) > this->end_of_mapping_plus1_)
+ if (this->grow_file_and_remap () == -1)
+ return 0;
+
+ return &this->get_pos_[offset];
+}
+
+off_t
+Mem_Map_Stream::seek (off_t offset, int whence)
+{
+ switch (whence)
+ {
+ case SEEK_SET:
+ this->get_pos_ =
+ reinterpret_cast<char *> (this->mem_map_.addr ())
+ + offset;
+ break;
+
+ case SEEK_CUR:
+ this->get_pos_ += offset;
+ break;
+
+ case SEEK_END:
+ this->get_pos_ =
+ this->end_of_mapping_plus1_ + offset;
+ // @@ Not sure how to implement this (yet).
+ ACE_NOTSUP_RETURN (-1);
+ break;
+ }
+
+ // Make sure that the backing store will cover this.
+ while (this->get_pos_ > this->end_of_mapping_plus1_)
+ if (this->grow_file_and_remap () == -1)
+ return (off_t) -1;
+
+ this->recv_pos_ = this->get_pos_;
+ return this->recv_pos_ - reinterpret_cast<char *> (this->mem_map_.addr ());
+}
+
+Mem_Map_Stream::Svc_Handler *
+Mem_Map_Stream::svc_handler (void)
+{
+ return this->svc_handler_;
+}
+
+
+int
+Mem_Map_Stream::open (STRAT_CONNECTOR *connector,
+ const ACE_INET_Addr &addr)
+{
+ svc_handler_ = 0;
+
+ // Connect to the server at <addr>. If the handler has to be
+ // connected to the server again, the Caching strategy takes care
+ // and uses the same connection.
+ if (connector->connect (svc_handler_,
+ addr) == -1)
+ {
+
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%p %s %d\n",
+ "Connect failed",
+ addr.get_host_name (),
+ addr.get_port_number ()),
+ -1);
+ }
+ // Create a temporary filename.
+ ACE_FILE_Addr file (ACE_sap_any_cast (ACE_FILE_Addr &));
+
+ // Create the temporary file via the <ACE_Mem_Map> class API.
+ if (this->mem_map_.open (file.get_path_name (),
+ O_RDWR | O_CREAT | O_APPEND,
+ ACE_DEFAULT_FILE_PERMS) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%p\n",
+ "open"),
+ -1);
+ // Make sure to unlink this right away so that if this process
+ // crashes these files will be removed automatically.
+#if 0
+ else if (ACE_OS::unlink (file.get_path_name ()) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%p\n",
+ "unlink"),
+ -1);
+ else
+#endif
+ // Initialize all the position pointers to 0.
+ this->rewind ();
+
+ return 0;
+}
+
+int
+Mem_Map_Stream::grow_file_and_remap (void)
+{
+ char buf[BUFSIZ + 1];
+
+ // Copy the next chunk of bytes from the socket into the temporary
+ // file.
+ ACE_Time_Value tv (*OPTIONS::instance ()->timeout ());
+
+ ssize_t n = this->svc_handler_->peer ().recv_n (buf,
+ sizeof buf,
+ 0,
+ &tv);
+ if (n == -1)
+ {
+ if (OPTIONS::instance ()->debug ())
+ ACE_ERROR ((LM_ERROR,
+ "%p\n",
+ "recv"));
+ return -1;
+ }
+ else if (n == 0)
+ return -1;
+ else if (ACE::write_n (this->mem_map_.handle (), buf, n) != n)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%p\n",
+ "write_n"),
+ -1);
+
+ // Grow the memory-mapping to encompass the entire temporary file.
+ if (this->mem_map_.map (-1,
+ PROT_RDWR,
+ ACE_MAP_PRIVATE | ACE_MAP_FIXED,
+ ACE_DEFAULT_BASE_ADDR) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%p\n",
+ "map"),
+ -1);
+ // MAP_FAILED is used as a "first time in" flag.
+ if (this->recv_pos_ == MAP_FAILED)
+ {
+ this->recv_pos_ = reinterpret_cast<char *> (this->mem_map_.addr ());
+ this->get_pos_ = this->recv_pos_;
+ }
+
+ this->end_of_mapping_plus1_ =
+ reinterpret_cast<char *> (this->mem_map_.addr ())
+ + this->mem_map_.size ();
+
+ return 0;
+}
+
+Mem_Map_Stream::~Mem_Map_Stream (void)
+{
+ // Remove the mapping and the file.
+ this->mem_map_.remove ();
+}
+
diff --git a/ACE/examples/Web_Crawler/Mem_Map_Stream.h b/ACE/examples/Web_Crawler/Mem_Map_Stream.h
new file mode 100644
index 00000000000..3595f04ab77
--- /dev/null
+++ b/ACE/examples/Web_Crawler/Mem_Map_Stream.h
@@ -0,0 +1,190 @@
+/* -*- C++ -*- */
+// $Id$
+
+// ============================================================================
+//
+// = LIBRARY
+// examples/Web_Crawler
+//
+// = FILENAME
+// Mem_Map_Stream.h
+//
+// = AUTHOR
+// Douglas C. Schmidt <schmidt@cs.wustl.edu>
+//
+// ============================================================================
+
+#ifndef _MEM_MAP_STREAM_H
+#define _MEM_MAP_STREAM_H
+#include /**/ "ace/pre.h"
+
+#include "ace/SOCK_Stream.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+#pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+
+#include "ace/Mem_Map.h"
+#include "ace/SOCK_Connector.h"
+#include "ace/Connector.h"
+#include "ace/Svc_Handler.h"
+#include "ace/Strategies_T.h"
+
+class Mem_Map_Stream
+{
+ // = TITLE
+ // Provides a memory-mapped stream abstraction to simplify parsing
+ // of tokens.
+ //
+ // = DESCRIPTION
+ // This class makes it possible to treat an connection as a stream
+ // of bytes, similar to the C library stdio streams. The contents
+ // of the connection are buffered incrementally in a memory-mapped
+ // file. This class maintains pointers to two positions in the
+ // stream:
+ //
+ // 1. The <recv> position, which keeps track of the beginning of a
+ // token that is in the stream.
+ //
+ // 2. The <get> position, which moves along character-by-character
+ // until the end of the token is reached.
+ //
+ // Once a token has been located, it can be extracted from the
+ // stream by calling the <recv>. The length of the token, i.e.,
+ // the <recv_len>, is the length in bytes between the <get>
+ // position and the <recv> position. Once the token has been
+ // extracted, the <recv> and <get> positions can be updated by the
+ // <seek> method.
+
+public:
+ typedef ACE_Svc_Handler<ACE_SOCK_STREAM, ACE_NULL_SYNCH> Svc_Handler;
+
+ typedef ACE_Strategy_Connector<Svc_Handler,
+ ACE_SOCK_CONNECTOR>
+ STRAT_CONNECTOR;
+
+ // Mem_Map_Stream (void);
+ // constructor added:KIRTHIKA
+ virtual int open (STRAT_CONNECTOR *connector,
+ const ACE_INET_Addr &);
+ // Initialize this object.
+
+ virtual ~Mem_Map_Stream (void);
+ // Destructor.
+
+ // = Accessor.
+ ACE_SOCK_Stream &stream (void);
+ // Returns the underlying <ACE_SOCK_Stream>.
+
+ // = I/O methods.
+
+ virtual ssize_t send_n (const void *buf,
+ size_t size,
+ ACE_Time_Value *tv = 0);
+ // Send <size> bytes in <buf> to the connected peer. This is a
+ // completely unbuffered call.
+
+ virtual int get_char (void);
+ // Return the next character in the stream and advance the <get>
+ // position. Returns EOF when the <get> position reaches the end of
+ // the HTTP stream.
+
+ virtual const char *recv (size_t &len);
+ // Returns a pointer to array of at most <len> characters starting
+ // at the <recv> position. If the <recv> position + <len> extends
+ // past the EOF then <len> is set to the number of characters
+ // between the <recv> position and the EOF and both the <get> and
+ // <recv> positions are advanced by <len>. Returns 0 if the <recv>
+ // position is at the EOF.
+
+ virtual const char *recv (void) const;
+ // Returns a pointer to array of characters starting at the <recv>
+ // position.
+
+ virtual size_t recv_len (void) const;
+ // Returns the length in bytes between the <get> position and the
+ // <recv> position.
+
+ virtual int rewind (void);
+ // Resets the <get> and <recv> positions to the beginning of the
+ // stream. This works since all the data has been cached in the
+ // memory-mapped backing store.
+
+ virtual int peek_char (size_t offset);
+ // Returns the nth character <offset> from the <get> position in the
+ // stream without advancing the <get> position. Automatically
+ // extends the backing store if necessary. Returns EOF if <offset>
+ // is past the end of the stream.
+
+ virtual const char *peek_str (size_t offset, size_t size);
+ // Return a pointer to an array of <size> characters starting at
+ // <offset> characters from the <get> position in the stream without
+ // advancing the <get> position. Automatically extends the backing
+ // store if necessary. Returns 0 if <offset> or <offset + size> is
+ // past the end of the stream.
+
+ virtual off_t seek (off_t offset, int whence = SEEK_CUR);
+ // Sets the <get> and <recv> positions as follows:
+ // o If <whence> is <SEEK_SET>, the positions are set to <offset>
+ // bytes from the start of the stream.
+ //
+ // o If <whence> is <SEEK_CUR>, the positions are set to the
+ // current <get> position plus <offset>.
+ //
+ // o If <whence> is <SEEK_END>, the positions are set to the size
+ // of the stream plus <offset>.
+
+ virtual int eof (void) const;
+ // Returns 1 if we're at the end of the HTTP stream, else 0.
+
+
+ /*
+ typedef ACE_NOOP_Creation_Strategy<Svc_Handler>
+ NULL_CREATION_STRATEGY;
+ typedef ACE_NOOP_Concurrency_Strategy<Svc_Handler>
+ NULL_ACTIVATION_STRATEGY;
+ typedef ACE_Cached_Connect_Strategy<Svc_Handler,
+ ACE_SOCK_CONNECTOR,
+ ACE_SYNCH_NULL_MUTEX>
+ CACHED_CONNECT_STRATEGY;*/
+
+ Svc_Handler *svc_handler (void);
+
+private:
+ int grow_file_and_remap (void);
+ // Grow the file by reading another chunk from the HTTP socket and
+ // extend the mapping to cover this chunk. Returns -1 on failure or
+ // EOF, else 0.
+
+ //ACE_SOCK_Stream stream_;
+
+ Svc_Handler *svc_handler_;
+ // Connection to peer. The granularity is at the Svc_Handler level.
+ // The Svc_Handler has an SOCK_Stream.
+ /*
+ NULL_CREATION_STRATEGY creation_strategy_;
+ NULL_ACTIVATION_STRATEGY activation_strategy_;
+ // Configure the Strategy Connector with a strategy that caches
+ // connection.
+ CACHED_CONNECT_STRATEGY caching_connect_strategy_;
+
+ STRAT_CONNECTOR *strat_connector_; */
+
+ ACE_Mem_Map mem_map_;
+ // Memory-mapped file that we're iterating over.
+
+ char *recv_pos_;
+ // Pointer to the address where the next <recv> method will start.
+
+ char *get_pos_;
+ // Pointer to the address where the next <get_char> method will
+ // start.
+
+ char *end_of_mapping_plus1_;
+ // Address at the end of the file mapping.
+
+};
+
+#include /**/ "ace/post.h"
+#endif /* _MEM_MAP_STREAM_H */
diff --git a/ACE/examples/Web_Crawler/Options.cpp b/ACE/examples/Web_Crawler/Options.cpp
new file mode 100644
index 00000000000..389cbfa0733
--- /dev/null
+++ b/ACE/examples/Web_Crawler/Options.cpp
@@ -0,0 +1,177 @@
+// $Id$
+
+#include "ace/Get_Opt.h"
+#include "ace/Log_Msg.h"
+#include "URL_Addr.h"
+#include "Options.h"
+#include "ace/OS_NS_string.h"
+
+ACE_RCSID(Web_Crawler, Options, "$Id$")
+
+int
+Options::parse_args (int argc, ACE_TCHAR *argv[])
+{
+ ACE_Get_Opt getopt (argc, argv, ACE_TEXT ("df:h:i:l:rt:u:vo:p:"));
+
+ ACE_LOG_MSG->open (argv[0]);
+
+ this->hostname_ = ACE_TEXT ("www.cs.wustl.edu");
+ this->uri_ = ACE_TEXT ("index.html");
+ this->recurse_ = 0;
+ this->debug_ = 0;
+ this->timeout_.sec (ACE_DEFAULT_TIMEOUT);
+ this->url_filter_ = 0;
+ this->verbose_ = 0;
+ this->order_ = ACE_TEXT ("FIFO");
+ this->port_no_ = ACE_DEFAULT_HTTP_PORT;
+
+ // The default is to make this limit as large as possible.
+ this->handle_limit_ = -1;
+
+ for (int c;
+ (c = getopt ()) != EOF;
+ )
+ switch (c)
+ {
+ case ACE_TEXT ('d'):
+ this->debug_ = 1;
+ break;
+ case ACE_TEXT ('f'):
+ this->url_filter_ = getopt.opt_arg ();
+ break;
+ case ACE_TEXT ('h'):
+ this->hostname_ = getopt.opt_arg ();
+ break;
+ case ACE_TEXT ('i'):
+ this->uri_ = getopt.opt_arg ();
+ break;
+ case ACE_TEXT ('l'):
+ this->handle_limit_ = ACE_OS::atoi (getopt.opt_arg ());
+ break;
+ case ACE_TEXT ('r'):
+ this->recurse_ = 1;
+ break;
+ case ACE_TEXT ('t'):
+ this->timeout_.sec (ACE_OS::atoi (getopt.opt_arg ()));
+ break;
+ case ACE_TEXT ('u'):
+ {
+ this->hostname_ = getopt.opt_arg ();
+ ACE_TCHAR *s = ACE_OS::strchr (getopt.opt_arg (), ACE_TEXT ('/'));
+ if (s != 0)
+ {
+ this->uri_ = s + 1;
+ *s = ACE_TEXT ('\0');
+ }
+ else
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("invalid URL %s\n"),
+ getopt.opt_arg ()));
+ }
+ break;
+ case ACE_TEXT ('v'):
+ this->verbose_ = 1;
+ break;
+ case ACE_TEXT ('o'):
+ {
+ this->order_ = getopt.opt_arg ();
+ }
+ break;
+ case ACE_TEXT ('p'):
+ this->port_no_ = ACE_OS::atoi (getopt.opt_arg ());
+ break;
+ default:
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("usage: %n [-d] [-f filter] [-h hostname]")
+ ACE_TEXT (" [-l handle-limit] [-r] [-t timeout] [-u URI]")
+ ACE_TEXT (" [-v]\n%a"),
+ 1));
+
+ /* NOTREACHED */
+ }
+
+ return 0;
+}
+
+int
+Options::port_no (void) const
+{
+ return this->port_no_;
+}
+
+int
+Options::recurse (void) const
+{
+ return this->recurse_;
+}
+
+const ACE_Time_Value *
+Options::timeout (void) const
+{
+ return &this->timeout_;
+}
+
+int
+Options::debug (void) const
+{
+ return this->debug_;
+}
+
+int
+Options::verbose (void) const
+{
+ return this->verbose_;
+}
+
+const ACE_TCHAR *
+Options::order (void) const
+{
+ return this->order_;
+}
+const ACE_TCHAR *
+Options::hostname (void) const
+{
+ return this->hostname_;
+}
+
+const ACE_TCHAR *
+Options::path_name (void) const
+{
+ return this->uri_;
+}
+
+const ACE_TCHAR *
+Options::url_filter (void) const
+{
+ return this->url_filter_;
+}
+
+Command_Processor *
+Options::command_processor (void) const
+{
+ return this->command_processor_;
+}
+
+void
+Options::command_processor (Command_Processor *cp)
+{
+ this->command_processor_ = cp;
+}
+
+URL_Visitor *
+Options::visitor (void) const
+{
+ return this->visitor_;
+}
+
+void
+Options::visitor (URL_Visitor *v)
+{
+ this->visitor_ = v;
+}
+
+int
+Options::handle_limit (void)
+{
+ return this->handle_limit_;
+}
diff --git a/ACE/examples/Web_Crawler/Options.h b/ACE/examples/Web_Crawler/Options.h
new file mode 100644
index 00000000000..ef5f2efd40c
--- /dev/null
+++ b/ACE/examples/Web_Crawler/Options.h
@@ -0,0 +1,124 @@
+/* -*- C++ -*- */
+// $Id$
+
+// ============================================================================
+//
+// = LIBRARY
+// examples/Web_Crawler
+//
+// = FILENAME
+// Options.h
+//
+// = AUTHOR
+// Douglas C. Schmidt <schmidt@cs.wustl.edu>
+//
+// ============================================================================
+
+#ifndef _OPTIONS_H
+#define _OPTIONS_H
+
+#include "ace/Null_Mutex.h"
+#include "ace/Singleton.h"
+#include "ace/Time_Value.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+#pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+// Forward decls.
+class Command_Processor;
+class URL_Visitor;
+
+class Options
+{
+ // = TITLE
+ // Maintains the global options.
+ //
+ // = DESCRIPTION
+ // This class is converted into a Singleton by the
+ // <ACE_Singleton> template.
+public:
+ int parse_args (int argc, ACE_TCHAR *argv[]);
+ // Parse the command-line arguments and initialize the options.
+
+ int recurse (void) const;
+ // If non-0 and the link is an HTML file then recursively check all
+ // links that are embedded in the body of file.
+
+ const ACE_TCHAR *hostname (void) const;
+ // Return the hostname of the initial Web server.
+
+ const ACE_TCHAR *path_name (void) const;
+ // Return the initial URI.
+
+ const ACE_TCHAR *url_filter (void) const;
+ // String used to filter out which URLs to validate.
+
+ int debug (void) const;
+ // Are we debugging?
+
+ int verbose (void) const;
+ // Are we being verbose?
+
+ const ACE_TCHAR *order (void) const;
+ // Which order? LIFO|FIFO??
+
+ int port_no (void) const;
+ // Port #
+
+ const ACE_Time_Value *timeout (void) const;
+ // Return the timeout used to prevent hanging on <recv> and
+ // <connect> calls to broken servers.
+
+ // = Get/set the <Command_Processor>.
+ Command_Processor *command_processor (void) const;
+ void command_processor (Command_Processor *);
+
+ // = Get/set the <URL_Visitor>.
+ URL_Visitor *visitor (void) const;
+ void visitor (URL_Visitor *);
+
+ // Get the handle_limit.
+ int handle_limit (void);
+private:
+ int recurse_;
+ // Are we recursving.
+
+ const ACE_TCHAR *hostname_;
+ // Initial Web server name.
+
+ const ACE_TCHAR *uri_;
+ // Initial URI name.
+
+ int debug_;
+ // Are we debugging?
+
+ int verbose_;
+ // Are we being verbose?
+
+ const ACE_TCHAR *order_;
+ // Whether the URLs are traversed in FIFO or LIFO order.
+
+ ACE_Time_Value timeout_;
+ // Timeout on <recv> and <connect> to broken Web servers.
+
+ const ACE_TCHAR *url_filter_;
+ // String used to filter out which URLs to validate.
+
+ Command_Processor *command_processor_;
+ // Pointer to the Command_Processor.
+
+ URL_Visitor *visitor_;
+ // Pointer to the <URL_Visitor>.
+
+ int port_no_;
+ // Port no.
+
+ int handle_limit_;
+ // The limit of the number of descriptors to be given for this process.
+};
+
+// Typedef an Options Singleton.
+typedef ACE_Singleton <Options, ACE_Null_Mutex> OPTIONS;
+
+#endif /* _OPTIONS_H */
diff --git a/ACE/examples/Web_Crawler/README b/ACE/examples/Web_Crawler/README
new file mode 100644
index 00000000000..4f81809173d
--- /dev/null
+++ b/ACE/examples/Web_Crawler/README
@@ -0,0 +1,25 @@
+Web Crawler Kirthika Parameswaran
+-----------
+
+The Web Crawler follows the HTTP_1.1 protocol.
+
+This Crawler crawls in either FIFO or LIFO order over the URLs
+now stored in a ACE_Unbounded_Queue. The Command Processor pattern is
+used in this example.
+
+Also the auto-purging feature where connections are removed from the cache
+when the process runs out of file descriptors, is added to this example.
+
+[Use the -l option to set the handle limit].
+
+Run:
+---
+
+
+> make
+
+> main -r -u www.cs.wustl.edu/~kirthika/test.html -o LIFO
+
+or
+
+> main -r -u www.cs.wustl.edu/~kirthika/test.html -o FIFO
diff --git a/ACE/examples/Web_Crawler/URL.cpp b/ACE/examples/Web_Crawler/URL.cpp
new file mode 100644
index 00000000000..ce52ed892ad
--- /dev/null
+++ b/ACE/examples/Web_Crawler/URL.cpp
@@ -0,0 +1,39 @@
+// $Id$
+
+#include "URL.h"
+
+ACE_RCSID(Web_Crawler, URL, "$Id$")
+
+Mem_Map_Stream &
+URL::stream (void)
+{
+ return this->stream_;
+}
+
+URL::~URL (void)
+{
+}
+
+const URL_Status &
+URL::reply_status (void)
+{
+ return this->reply_status_;
+}
+
+void
+URL::reply_status (const URL_Status &rs)
+{
+ this->reply_status_ = rs;
+}
+
+const ACE_CString &
+URL::content_type (void)
+{
+ return this->content_type_;
+}
+
+void
+URL::content_type (const ACE_CString &ct)
+{
+ this->content_type_ = ct;
+}
diff --git a/ACE/examples/Web_Crawler/URL.h b/ACE/examples/Web_Crawler/URL.h
new file mode 100644
index 00000000000..68c41f018ad
--- /dev/null
+++ b/ACE/examples/Web_Crawler/URL.h
@@ -0,0 +1,82 @@
+/* -*- C++ -*- */
+// $Id$
+
+// ============================================================================
+//
+// = LIBRARY
+// examples/Web_Crawler
+//
+// = FILENAME
+// URL.h
+//
+// = AUTHOR
+// Douglas C. Schmidt <schmidt@cs.wustl.edu>
+//
+// ============================================================================
+
+#ifndef _URL_H
+#define _URL_H
+
+#include "Mem_Map_Stream.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+#pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "URL_Addr.h"
+#include "URL_Status.h"
+
+#include "ace/SString.h"
+
+
+// Forward declaration.
+class URL_Visitor;
+
+class URL
+{
+ // = TITLE
+ // Base class for a URL.
+ //
+ // = DESCRIPTION
+ // This class plays a role in the Visitor pattern.
+public:
+ virtual ~URL (void);
+ // Destructor.
+
+ virtual int accept (URL_Visitor *visitor) = 0;
+ // Accept the visitor, which will then perform a particular
+ // visitation strategy on the URL. This method is part of the
+ // Visitor pattern.
+
+ virtual ssize_t send_request (void) = 0;
+ // Send a <GET> command to fetch the contents in the URI from the
+ // server.
+
+ virtual const ACE_URL_Addr &url_addr (void) const = 0;
+ // Returns the URL that we represent.
+
+ virtual Mem_Map_Stream &stream (void);
+ // Returns the <Mem_Map_Stream>.
+
+ // = Get/set the reply status.
+ virtual const URL_Status &reply_status (void);
+ virtual void reply_status (const URL_Status &);
+
+ // = Get/set the reply status.
+ virtual const ACE_CString &content_type (void);
+ virtual void content_type (const ACE_CString &);
+
+
+
+private:
+ URL_Status reply_status_;
+ // Reply status of the URL.
+
+ ACE_CString content_type_;
+ // Content-type of the URL.
+
+ Mem_Map_Stream stream_;
+ // Contents of the stream.
+};
+
+#endif /* _URL_H */
diff --git a/ACE/examples/Web_Crawler/URL_Addr.cpp b/ACE/examples/Web_Crawler/URL_Addr.cpp
new file mode 100644
index 00000000000..5a630e387fb
--- /dev/null
+++ b/ACE/examples/Web_Crawler/URL_Addr.cpp
@@ -0,0 +1,234 @@
+// $Id$
+
+#include "URL_Addr.h"
+#include "ace/Log_Msg.h"
+#include "ace/OS_NS_string.h"
+#include "ace/OS_NS_stdio.h"
+#include "ace/OS_NS_stdlib.h"
+#include "ace/OS_Memory.h"
+
+ACE_RCSID (Web_Crawler,
+ URL_Addr,
+ "$Id$")
+
+
+ACE_URL_Addr::ACE_URL_Addr (void)
+ : path_name_ (0),
+ addr_string_ (0),
+ addr_string_len_ (0)
+{
+}
+
+int
+ACE_URL_Addr::addr_to_string (ACE_TCHAR *s,
+ size_t size,
+ int ipaddr_format) const
+{
+ const size_t total_len =
+ ACE_OS::strlen (ipaddr_format == 0 ?
+ this->get_host_name () :
+ this->get_host_addr ())
+ + ACE_OS::strlen ("65536") // Assume the max port number.
+ + ACE_OS::strlen (this->get_path_name ())
+ + sizeof (':')
+ + sizeof ('/')
+ + sizeof ('\0'); // For trailing '\0'.
+
+ if (size < total_len)
+ return -1;
+ else
+ {
+ ACE_OS::sprintf (s, ACE_TEXT ("%s:%d/%s"),
+ ACE_TEXT_CHAR_TO_TCHAR (ipaddr_format == 0
+ ? this->get_host_name ()
+ : this->get_host_addr ()),
+ this->get_port_number (),
+ this->get_path_name ());
+ return 0;
+ }
+}
+
+const ACE_TCHAR *
+ACE_URL_Addr::addr_to_string (int ipaddr_format) const
+{
+ ACE_URL_Addr *this_ptr = const_cast<ACE_URL_Addr *> (this);
+
+ size_t size =
+ ACE_OS::strlen (ipaddr_format == 0 ?
+ this->get_host_name () :
+ this->get_host_addr ())
+ + ACE_OS::strlen ("65536") // Assume the max port number.
+ + ACE_OS::strlen (this->get_path_name ())
+ + sizeof (':')
+ + sizeof ('/')
+ + sizeof ('\0'); // For trailing '\0'.
+
+ if (size > this->addr_string_len_)
+ {
+ ACE_ALLOCATOR_RETURN (this_ptr->addr_string_,
+ (ACE_TCHAR *) ACE_OS::realloc ((void *) this->addr_string_,
+ size),
+ 0);
+ this_ptr->addr_string_len_ = size;
+ }
+ ACE_OS::sprintf (this->addr_string_,
+ ACE_TEXT ("%s:%d/%s"),
+ ACE_TEXT_CHAR_TO_TCHAR (ipaddr_format == 0
+ ? this->get_host_name ()
+ : this->get_host_addr ()),
+ this->get_port_number (),
+ this->get_path_name ());
+ return this->addr_string_;
+}
+
+int
+ACE_URL_Addr::string_to_addr (const ACE_TCHAR *s)
+{
+ int result;
+ ACE_TCHAR *t;
+
+ // Need to make a duplicate since we'll be overwriting the string.
+ ACE_ALLOCATOR_RETURN (t,
+ ACE_OS::strdup (s),
+ -1);
+
+
+ // First split off the path_name.
+
+ ACE_TCHAR *path_name = ACE_OS::strchr (t, ACE_TEXT ('/'));
+ const ACE_TCHAR *name = ACE_TEXT ("index.html");
+ if (path_name != 0)
+ {
+ if (ACE_OS::strlen (path_name + 1) > 0)
+ name = path_name + 1;
+
+ *path_name = '\0';
+ }
+
+ ACE_ALLOCATOR_RETURN (this->path_name_,
+ // Skip over '/'
+ ACE_OS::strdup (name),
+ -1);
+
+ // Now handle the host address and port number.
+ ACE_TCHAR *port_number = ACE_OS::strchr (t, ':');
+
+ if (port_number == 0)
+ {
+ // Assume it's an ip-address or ip-number.
+ result = this->ACE_INET_Addr::set (ACE_DEFAULT_HTTP_PORT,
+ t);
+ }
+ else
+ {
+ *port_number = '\0';
+ u_short port = (u_short) ACE_OS::atoi (port_number + 1); // Skip over ':'
+ result = this->ACE_INET_Addr::set (port, t);
+ }
+
+ ACE_OS::free (ACE_MALLOC_T (t));
+ return result;
+}
+
+ACE_URL_Addr::ACE_URL_Addr (const ACE_URL_Addr &addr)
+ : ACE_INET_Addr (),
+ path_name_ (0),
+ addr_string_ (0),
+ addr_string_len_ (0)
+{
+ if (this->set (addr) == -1)
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("ACE_URL_Addr::ACE_URL_Addr")));
+}
+
+int
+ACE_URL_Addr::set (const ACE_URL_Addr &addr)
+{
+ ACE_OS::free (reinterpret_cast<void *> (const_cast<ACE_TCHAR *>
+ (this->path_name_)));
+ ACE_OS::free (reinterpret_cast<void *> (const_cast<ACE_TCHAR *>
+ (this->addr_string_)));
+ if (this->ACE_INET_Addr::set (addr) == -1)
+ return -1;
+ else
+ {
+ if (addr.path_name_)
+ ACE_ALLOCATOR_RETURN (this->path_name_,
+ ACE_OS::strdup (addr.path_name_),
+ -1);
+ if (addr.addr_string_)
+ ACE_ALLOCATOR_RETURN (this->addr_string_,
+ ACE_OS::strdup (addr.addr_string_),
+ -1);
+ this->addr_string_len_ =
+ addr.addr_string_len_;
+ return 0;
+ }
+}
+
+void
+ACE_URL_Addr::operator= (const ACE_URL_Addr &addr)
+{
+ if (this->set (addr) == -1)
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("ACE_URL_Addr::ACE_URL_Addr")));
+}
+
+u_long
+ACE_URL_Addr::hash (void) const
+{
+ u_long result = this->ACE_INET_Addr::hash ()
+ + ACE::hash_pjw (this->get_path_name ());
+
+ return result;
+}
+
+bool
+ACE_URL_Addr::operator== (const ACE_URL_Addr &addr) const
+{
+ return ACE_OS::strcmp (addr.get_path_name (),
+ this->get_path_name ()) == 0
+ && addr.get_port_number () == this->get_port_number ()
+ && addr.get_ip_address () == this->get_ip_address ();
+}
+
+bool
+ACE_URL_Addr::operator!= (const ACE_URL_Addr &addr) const
+{
+ return !(*this == addr);
+}
+
+ACE_URL_Addr::ACE_URL_Addr (const ACE_TCHAR *host_name,
+ const ACE_TCHAR *path_name,
+ u_short port)
+ : ACE_INET_Addr (port, host_name),
+ path_name_ (ACE_OS::strdup (path_name)),
+ addr_string_ (0),
+ addr_string_len_ (0)
+{
+}
+
+const ACE_TCHAR *
+ACE_URL_Addr::get_path_name (void) const
+{
+ return this->path_name_;
+}
+
+ACE_URL_Addr::~ACE_URL_Addr (void)
+{
+ ACE_OS::free (reinterpret_cast<void *> (const_cast<ACE_TCHAR *>
+ (this->path_name_)));
+ ACE_OS::free (reinterpret_cast<void *> (const_cast<ACE_TCHAR *>
+ (this->addr_string_)));
+ this->path_name_ = 0;
+}
+
+int
+ACE_URL_Addr::destroy (void)
+{
+ // Commit suicide.
+ delete this;
+ return 0;
+}
diff --git a/ACE/examples/Web_Crawler/URL_Addr.h b/ACE/examples/Web_Crawler/URL_Addr.h
new file mode 100644
index 00000000000..9792e1bb390
--- /dev/null
+++ b/ACE/examples/Web_Crawler/URL_Addr.h
@@ -0,0 +1,111 @@
+// -*- C++ -*-
+
+// $Id$
+
+// ============================================================================
+//
+// = LIBRARY
+// examples/Web_Crawler
+//
+// = FILENAME
+// URL_Addr.h
+//
+// = AUTHOR
+// Douglas C. Schmidt <schmidt@cs.wustl.edu>
+//
+// ============================================================================
+
+#ifndef ACE_URL_ADDR_H
+#define ACE_URL_ADDR_H
+
+#include "ace/INET_Addr.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+#pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/ACE.h"
+
+class ACE_URL_Addr : public ACE_INET_Addr
+{
+ // = TITLE
+ // Defines a URL address family address format.
+public:
+ // = Initialization and termination methods.
+ ACE_URL_Addr (void);
+ // Constructor.
+
+ ACE_URL_Addr (const ACE_TCHAR *host_name,
+ const ACE_TCHAR *path_name,
+ u_short port = ACE_DEFAULT_HTTP_PORT);
+
+ ACE_URL_Addr (const ACE_URL_Addr &addr);
+ // Copy constructor.
+
+ int set (const ACE_URL_Addr &addr);
+ // Essentially the copy constructor.
+
+ virtual int string_to_addr (const ACE_TCHAR *address);
+ // Initializes an <ACE_URL_Addr> from the <address>, which can be
+ // "ip-number:port-number/path-name" (e.g.,
+ // "www.cs.wustl.edu:1234/~schmidt/" "ip-number:port-number/path-name"
+ // (e.g., "128.252.166.57:1234/~schmidt"). If there is no ':' in
+ // the <address> it is assumed to be an ip-number or ip-address
+ // number, with the port number <ACE_DEFAULT_HTTP_PORT>.
+
+ virtual int addr_to_string (ACE_TCHAR *s,
+ size_t size,
+ int ipaddr_format = 1) const;
+ // Transform the current <ACE_INET_Addr> address into string format.
+ // If <ipaddr_format> is non-0 this produces
+ // "ip-number:port-number/path-name" (e.g.,
+ // "128.252.166.57:80/~schmidt/"), whereas if <ipaddr_format> is 0
+ // this produces "ip-name:port-number" (e.g.,
+ // "www.cs.wustl.edu:80/~schmidt/"). Returns -1 if the <size> of
+ // the <buffer> is too small, else 0.
+
+ virtual const ACE_TCHAR *addr_to_string (int ipaddr_format = 1) const;
+ // Transform the current <ACE_INET_Addr> address into string format.
+ // If <ipaddr_format> is non-0 this produces
+ // "ip-number:port-number/path-name" (e.g.,
+ // "128.252.166.57:80/~schmidt/"), whereas if <ipaddr_format> is 0
+ // this produces "ip-name:port-number" (e.g.,
+ // "www.cs.wustl.edu:80/~schmidt/"). Uses dynamic memory, which
+ // is allocated on demand and deallocated when the object is
+ // destroyed. Returns -1 if dynamic memory fails, else 0.
+
+ void operator= (const ACE_URL_Addr &addr);
+ // Assignment operator.
+
+ ~ACE_URL_Addr (void);
+ // Destructor.
+
+ bool operator == (const ACE_URL_Addr &SAP) const;
+ // Compare two addresses for equality. The addresses are considered
+ // equal if they contain the same IP address, port number, and path
+ // name.
+
+ bool operator != (const ACE_URL_Addr &SAP) const;
+ // Compare two addresses for inequality.
+
+ virtual u_long hash (void) const;
+ // Computes and returns hash value.
+
+ const ACE_TCHAR *get_path_name (void) const;
+ // Return the path name.
+
+ int destroy (void);
+ // Commit suicide.
+private:
+ ACE_TCHAR *path_name_;
+ // Our path name.
+
+ ACE_TCHAR *addr_string_;
+ // The dynamically address string that's used for the
+ // <addr_to_string> method.
+
+ size_t addr_string_len_;
+ // Current length of the <addr_string_>
+};
+
+#endif /* ACE_URL_ADDR_H */
diff --git a/ACE/examples/Web_Crawler/URL_Status.cpp b/ACE/examples/Web_Crawler/URL_Status.cpp
new file mode 100644
index 00000000000..35a57420593
--- /dev/null
+++ b/ACE/examples/Web_Crawler/URL_Status.cpp
@@ -0,0 +1,40 @@
+/* -*- C++ -*- */
+// $Id$
+
+#include "URL_Status.h"
+
+ACE_RCSID(Web_Crawler, URL_Status, "$Id$")
+
+URL_Status::URL_Status (STATUS_CODE code)
+ : status_ (code)
+{
+}
+
+URL_Status::URL_Status (const URL_Status &s)
+ : status_ (s.status_)
+{
+}
+
+URL_Status::STATUS_CODE
+URL_Status::status (void) const
+{
+ return this->status_;
+}
+
+void
+URL_Status::status (int s)
+{
+ this->status_ = URL_Status::STATUS_CODE (s);
+}
+
+void
+URL_Status::status (URL_Status::STATUS_CODE s)
+{
+ this->status_ = s;
+}
+
+int URL_Status::destroy (void)
+{
+ delete this;
+ return 0;
+}
diff --git a/ACE/examples/Web_Crawler/URL_Status.h b/ACE/examples/Web_Crawler/URL_Status.h
new file mode 100644
index 00000000000..672c5e4f240
--- /dev/null
+++ b/ACE/examples/Web_Crawler/URL_Status.h
@@ -0,0 +1,61 @@
+/* -*- C++ -*- */
+// $Id$
+
+// ============================================================================
+//
+// = LIBRARY
+// examples/Web_Crawler
+//
+// = FILENAME
+// URL_Status.h
+//
+// = AUTHOR
+// Douglas C. Schmidt <schmidt@cs.wustl.edu>
+//
+// ============================================================================
+
+#ifndef _URL_STATUS_H
+#define _URL_STATUS_H
+
+#include "ace/config-all.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+#pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+class URL_Status
+{
+ // = TITLE
+public:
+ enum STATUS_CODE
+ {
+ STATUS_OK = 200,
+ STATUS_CREATED = 201,
+ STATUS_ACCEPTED = 202,
+ STATUS_NO_CONTENT = 204,
+ STATUS_MOVED_PERMANENTLY = 301,
+ STATUS_MOVED_TEMPORARILY = 302,
+ STATUS_NOT_MODIFIED = 304,
+ STATUS_BAD_REQUEST = 400,
+ STATUS_UNAUTHORIZED = 401,
+ STATUS_FORBIDDEN = 403,
+ STATUS_ITEM_NOT_FOUND = 404,
+ STATUS_INTERNAL_SERVER_ERROR = 500,
+ STATUS_OP_NOT_IMPLEMENTED = 501,
+ STATUS_BAD_GATEWAY = 502,
+ STATUS_SERVICE_UNAVAILABLE = 503,
+ STATUS_INSUFFICIENT_DATA = 399
+ };
+
+ URL_Status (STATUS_CODE = STATUS_INSUFFICIENT_DATA);
+ URL_Status (const URL_Status &);
+
+ STATUS_CODE status (void) const;
+ void status (int);
+ void status (STATUS_CODE);
+ int destroy (void);
+private:
+ STATUS_CODE status_;
+};
+
+#endif /* _URL_STATUS_H */
diff --git a/ACE/examples/Web_Crawler/URL_Visitor.cpp b/ACE/examples/Web_Crawler/URL_Visitor.cpp
new file mode 100644
index 00000000000..481a7140089
--- /dev/null
+++ b/ACE/examples/Web_Crawler/URL_Visitor.cpp
@@ -0,0 +1,543 @@
+// $Id$
+
+#include "ace/OS_NS_string.h"
+#include "URL_Visitor.h"
+#include "Command_Processor.h"
+
+ACE_RCSID(Web_Crawler, URL_Visitor, "$Id$")
+
+URL_Processing_Strategy::URL_Processing_Strategy (URL &url,
+ URL_Iterator &iterator)
+ : url_ (url),
+ iterator_ (iterator)
+{
+}
+
+URL_Processing_Strategy::~URL_Processing_Strategy (void)
+{
+}
+
+int
+URL_Processing_Strategy::destroy (void)
+{
+ // Commit suicide.
+ delete this;
+ return 0;
+}
+
+URL_Download_Strategy::URL_Download_Strategy (URL &url,
+ URL_Iterator &iterator)
+ : URL_Processing_Strategy (url, iterator)
+{
+}
+
+int
+URL_Download_Strategy::execute (void)
+{
+ ACE_CString buffer;
+
+ // Extract all the contents of the Stream and print them to the
+ // file.
+ while (this->iterator_.next (buffer) != 0)
+ ACE_DEBUG ((LM_DEBUG,
+ "%s",
+ buffer.c_str ()));
+
+ return 0;
+}
+
+HTTP_Header_Processing_Strategy::HTTP_Header_Processing_Strategy (URL &url,
+ URL_Iterator &iterator)
+ : URL_Processing_Strategy (url, iterator)
+{
+}
+
+int
+HTTP_Header_Processing_Strategy::execute (void)
+{
+ // Set the get() position.Necessary since later a peek is done.
+ if (this->url_.stream ().get_char () == 0)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%p\n","Header Not Found"),
+ -1);
+ char line_buf[BUFSIZ + 1];
+ ACE_CString line (line_buf);
+ // Get the lines in the header iteratively and check for status info.
+ int result = 1, i = 0;
+ for (i = 0, result = this->iterator_.next (line);
+ result > 0;
+ ++i, result = this->iterator_.next (line))
+ {
+ if (i == 0)
+ {
+ // Assuming that the status-no is a space away.
+ int status_index = line.find ("HTTP", 0);
+ ACE_CString status = line.substring (status_index + 9, //HTTP/1.1 200
+ 3);
+
+ URL_Status *url_status = 0;
+ ACE_NEW_RETURN (url_status,
+ URL_Status,
+ 0);
+ Auto_Destroyer<URL_Status> url_status_ptr (url_status);
+ url_status_ptr->status (ACE_OS::atoi (status.c_str ()));
+ this->url_.reply_status (**url_status_ptr);
+ // Invalid url.
+ if (url_status_ptr->status () != 200)
+ return -1;
+ }
+ else
+ {
+
+ if (line.find ("text/html") != ACE_CString::npos)
+ {
+ ACE_CString url_content_type("text/html");
+ this->url_.content_type (url_content_type);
+ }
+ }
+ }
+ return 0;
+
+}
+
+HTML_Body_Validation_Strategy::HTML_Body_Validation_Strategy (URL &url,
+ URL_Iterator &iterator,
+ URL_Validation_Visitor &context)
+ : URL_Processing_Strategy (url, iterator),
+ visitor_context_ (context)
+{
+}
+
+int
+HTML_Body_Validation_Strategy::execute (void)
+{
+ char host_name_buf[BUFSIZ + 1];
+ ACE_CString host_name (host_name_buf);
+ host_name.set (url_.url_addr ().get_host_name (),1);
+
+ // All to facilitate relative paths
+ char temp[BUFSIZ + 1];
+ ACE_CString prev_location (temp);
+
+ prev_location.set (ACE_TEXT_ALWAYS_CHAR (this->url_.url_addr ().get_path_name ()),
+ ACE_OS::strlen (this->url_.url_addr ().get_path_name ()),
+ 1);
+ int index = prev_location.rfind ('/', prev_location.length ());
+ ACE_CString str = prev_location.substring (0, index + 1);
+ prev_location.set (str.c_str (), 1);
+
+ // Note: prev_location always ends with '/'
+ if (prev_location[0] != '/')
+ prev_location = "/" + prev_location;
+
+ // Build the url portion which can be attached to teh relative paths.
+ prev_location = host_name + prev_location;
+
+ char url_string[BUFSIZ + 1];
+ ACE_CString url (url_string);
+
+ while (this->iterator_.next (url) > 0)
+ {
+ // Check for relative urls.Strip out "http://" if its there.
+ if (url.find ("http") == url.npos)
+ {
+ if (url[0] == '.' && url[1] == '.')
+ {
+ url.set (&url[3], 1);
+ int i = prev_location.rfind ('/', prev_location.length () - 1);
+ prev_location = prev_location.substring (0, i+1);
+ }
+ if (url[0] == '.' && url[1] == '/')
+ url.set (&url[2], 1);
+
+ url = prev_location + url;
+ }
+ else
+ url.set (&url[7], 1);
+ // Double slash at the end works!e.g www.cs.wustl.edu/~kirthika//
+ if (url.find (".html") == url.npos)
+ url = url + "/";
+
+ // Create the new URL address.
+ ACE_URL_Addr *url_addr;
+ ACE_NEW_RETURN (url_addr,
+ ACE_URL_Addr,
+ 0);
+ Auto_Destroyer<ACE_URL_Addr> url_addr_ptr (url_addr);
+ if (url_addr_ptr->string_to_addr (ACE_TEXT_CHAR_TO_TCHAR (url.c_str ())) == 0)
+ {
+ HTTP_URL *http_url;
+ ACE_NEW_RETURN (http_url,
+ HTTP_URL (**url_addr_ptr,
+ dynamic_cast<HTTP_URL *> (&this->url_)),
+ 0);
+ URL_Command *url_command;
+ ACE_NEW_RETURN (url_command,
+ URL_Command (http_url),
+ 0);
+
+ OPTIONS::instance ()->command_processor ()->insert (url_command);
+ }
+ }
+ return 0;
+}
+
+URL_Iterator *
+URL_Validation_Visitation_Strategy_Factory::make_header_iterator (void)
+{
+ URL_Iterator *i;
+ ACE_NEW_RETURN (i,
+ HTTP_Header_Iterator (*this->url_),
+ 0);
+ return i;
+}
+
+URL_Iterator *
+URL_Validation_Visitation_Strategy_Factory::make_body_iterator (void)
+{
+ URL_Iterator *i;
+ ACE_NEW_RETURN (i,
+ HTML_Body_Iterator (*this->url_),
+ 0);
+ return i;
+}
+
+URL_Processing_Strategy *
+URL_Validation_Visitation_Strategy_Factory::make_header_strategy (URL_Iterator &iterator)
+{
+ URL_Processing_Strategy *ps;
+ ACE_NEW_RETURN (ps,
+ HTTP_Header_Processing_Strategy (*this->url_,
+ iterator),
+ 0);
+ return ps;
+}
+
+URL_Processing_Strategy *
+URL_Validation_Visitation_Strategy_Factory::make_body_strategy (URL_Iterator &iterator)
+{
+ URL_Processing_Strategy *ps;
+ ACE_NEW_RETURN (ps,
+ HTML_Body_Validation_Strategy (*this->url_,
+ iterator,
+ this->visitor_context_),
+ 0);
+ return ps;
+}
+
+int
+URL_Validation_Visitation_Strategy_Factory::destroy (void)
+{
+ // Commit suicide.
+ delete this;
+ return 0;
+}
+
+URL_Visitor::~URL_Visitor (void)
+{
+}
+
+URL_Validation_Visitor::URL_Validation_Visitor (void)
+{
+ ACE_NEW (this->caching_connect_strategy_,
+ CACHED_CONNECT_STRATEGY (this->caching_strategy_));
+ ACE_NEW (this->strat_connector_,
+ STRATEGY_CONNECTOR(0,
+ &creation_strategy_,
+ caching_connect_strategy_,
+ &activation_strategy_));
+ if (strat_connector_ == 0)
+ ACE_ERROR ((LM_ERROR,
+ "%p %s\n"
+ "strategy connector creation failed"));
+
+
+}
+
+URL_Validation_Visitor::~URL_Validation_Visitor (void)
+{
+ this->strat_connector_ = 0;
+ if (this->caching_connect_strategy_ != 0)
+ delete this->caching_connect_strategy_;
+}
+
+URL_Validation_Visitor::URL_CACHE &
+URL_Validation_Visitor::url_cache (void)
+{
+ return this->url_cache_;
+}
+
+int
+URL_Validation_Visitor::in_cache (const ACE_URL_Addr &url_addr)
+{
+ URL_Status reply_status (URL_Status::STATUS_CODE (1));
+
+ if (this->url_cache_.find (url_addr, reply_status) == 0)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ "status %d for URL %s (cached)\n",
+ reply_status.status (),
+ url_addr.addr_to_string (0)));
+
+ // Invalid status.
+ if (reply_status.status () != 200)
+ return -1;
+
+ return 1;
+ }
+ else
+ return 0;
+}
+
+URL_Visitation_Strategy_Factory *
+URL_Validation_Visitor::make_visitation_strategy_factory (URL &url)
+{
+ // Since this is HTTP 1.1 we'll need to establish a connection
+ // only once. Trying for relative paths.
+
+ if (url.stream ().open (this->strat_connector_,
+ url.url_addr ()) == -1)
+ return 0;
+
+ // See if we can get connected and send the GET request via the
+ // <HTTP_URL>.
+ int result = url.send_request ();
+ if (result == -1)
+ {
+ ACE_ERROR ((LM_ERROR,
+ "%p\n",
+ "send_request"));
+ if (this->url_cache_.bind (url.url_addr (),
+ URL_Status (URL_Status::STATUS_SERVICE_UNAVAILABLE)) == -1)
+ ACE_ERROR ((LM_ERROR,
+ "%p\n",
+ "bind"));
+ return 0;
+ }
+ // @@ Here's where we could check to see if the <url> was HTTP or
+ // FTP, etc. But for now we'll just assume that everything is an
+ // HTTP URL.
+ else
+ {
+
+ URL_Visitation_Strategy_Factory *vs;
+ ACE_NEW_RETURN (vs,
+ URL_Validation_Visitation_Strategy_Factory (&url,
+ *this),
+ 0);
+ return vs;
+ }
+}
+
+int
+URL_Validation_Visitor::destroy (void)
+{
+ delete this->strat_connector_;
+ // Commit suicide.
+ delete this;
+ return 0;
+}
+
+int
+URL_Validation_Visitor::visit (HTTP_URL &http_url)
+{
+ int result = this->in_cache (http_url.url_addr ());
+ if (result == 0)
+ {
+ Auto_Destroyer <URL_Visitation_Strategy_Factory> vs (this->make_visitation_strategy_factory (http_url));
+
+ if (*vs == 0)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%p\n",
+ "make_visitation_strategy_factory"),
+ -1);
+
+ Auto_Destroyer <URL_Iterator> ihs (vs->make_header_iterator ());
+ if (*ihs == 0)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%p\n",
+ "make_header_iterator"),
+ -1);
+ Auto_Destroyer <URL_Processing_Strategy> phs (vs->make_header_strategy (**ihs));
+ if (*phs == 0)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%p\n",
+ "make_header_strategy"),
+ -1);
+ int phs_result = phs->execute ();
+ if (phs_result == -1)
+ ACE_DEBUG ((LM_DEBUG,
+ "Invalid "));
+
+ ACE_DEBUG ((LM_DEBUG,
+ "URL with status %d %s\n",
+ http_url.reply_status ().status (),
+ http_url.url_addr().addr_to_string (0)));
+
+ // Store the http url in the cache.
+ if (this->url_cache ().bind (http_url.url_addr (),
+ http_url.reply_status ()) != 0)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%p\n","url_cache.bind"),
+ -1);
+
+ // Since it is invalid dont go further.
+ if (phs_result == -1)
+ return 0;
+
+ // Get back if the recurse option isnt set.
+ if (OPTIONS::instance ()->recurse () != 1)
+ return 0;
+
+ Auto_Destroyer <URL_Iterator> is (vs->make_body_iterator ());
+ if (*is == 0)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%p\n",
+ "make_body_iterator"),
+ -1);
+
+ Auto_Destroyer <URL_Processing_Strategy> ps (vs->make_body_strategy (**is));
+ if (*ps == 0)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%p\n",
+ "make_body_strategy"),
+ -1);
+
+ if (ps->execute () == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%p\n",
+ "body execute"),
+ -1);
+
+ }
+ return 0;
+}
+
+int
+URL_Download_Visitation_Strategy_Factory::destroy (void)
+{
+ // Commit suicide.
+ delete this;
+ return 0;
+}
+
+URL_Iterator *
+URL_Download_Visitation_Strategy_Factory::make_header_iterator (void)
+{
+ return 0;
+}
+
+URL_Iterator *
+URL_Download_Visitation_Strategy_Factory::make_body_iterator (void)
+{
+ URL_Iterator *i;
+ ACE_NEW_RETURN (i,
+ URL_Download_Iterator (*this->url_),
+ 0);
+ return i;
+}
+
+URL_Processing_Strategy *
+URL_Download_Visitation_Strategy_Factory::make_header_strategy (URL_Iterator &iterator)
+{
+ // You fill in here.
+ ACE_UNUSED_ARG (iterator);
+
+ return 0;
+}
+
+URL_Processing_Strategy *
+URL_Download_Visitation_Strategy_Factory::make_body_strategy (URL_Iterator &iterator)
+{
+ URL_Processing_Strategy *ps;
+ ACE_NEW_RETURN (ps,
+ URL_Download_Strategy (*this->url_,
+ iterator),
+ 0);
+ return ps;
+}
+
+URL_Visitation_Strategy_Factory::URL_Visitation_Strategy_Factory (URL *url)
+ : url_ (url)
+{
+}
+
+URL_Visitation_Strategy_Factory::~URL_Visitation_Strategy_Factory (void)
+{
+}
+
+URL_Download_Visitation_Strategy_Factory::URL_Download_Visitation_Strategy_Factory (URL *url)
+ : URL_Visitation_Strategy_Factory (url)
+{
+}
+
+URL_Validation_Visitation_Strategy_Factory::URL_Validation_Visitation_Strategy_Factory (URL *url,
+ URL_Validation_Visitor &visitor_context)
+ : URL_Visitation_Strategy_Factory (url),
+ visitor_context_ (visitor_context)
+{
+}
+
+URL_Visitation_Strategy_Factory *
+URL_Download_Visitor::make_visitation_strategy_factory (URL &url)
+{
+ // See if we can get connected and send the GET request via the
+ // <HTTP_URL>.
+ while (1)
+ {
+ int retval = url.send_request ();
+ if (retval != -1)
+ break;
+
+ }
+ // @@ Here's where we could check to see if the <url> was HTTP or
+ // FTP, etc. But for now we'll just assume that everything is an
+ // HTTP URL.
+ URL_Visitation_Strategy_Factory *vs;
+ ACE_NEW_RETURN (vs,
+ URL_Download_Visitation_Strategy_Factory (&url),
+ 0);
+ return vs;
+
+}
+
+int
+URL_Download_Visitor::destroy (void)
+{
+ // Commit suicide.
+ delete this;
+ return 0;
+}
+
+int
+URL_Download_Visitor::visit (HTTP_URL &http_url)
+{
+ Auto_Destroyer <URL_Visitation_Strategy_Factory> vs (this->make_visitation_strategy_factory (http_url));
+
+ if (*vs == 0)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%p\n",
+ "make_visitation_strategy_factory"),
+ -1);
+
+ Auto_Destroyer <URL_Iterator> is (vs->make_body_iterator ());
+ if (*is == 0)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%p\n",
+ "make_body_iterator"),
+ -1);
+
+ Auto_Destroyer <URL_Processing_Strategy> ps (vs->make_body_strategy (**is));
+ if (*ps == 0)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%p\n",
+ "make_body_strategy"),
+ -1);
+
+ if (ps->execute () == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%p\n",
+ "body execute"),
+ -1);
+ return 0;
+}
diff --git a/ACE/examples/Web_Crawler/URL_Visitor.h b/ACE/examples/Web_Crawler/URL_Visitor.h
new file mode 100644
index 00000000000..9f68612d629
--- /dev/null
+++ b/ACE/examples/Web_Crawler/URL_Visitor.h
@@ -0,0 +1,436 @@
+/* -*- C++ -*- */
+// $Id$
+
+// ============================================================================
+//
+// = LIBRARY
+// examples/Web_Crawler
+//
+// = FILENAME
+// URL_Visitor.h
+//
+// = AUTHOR
+// Douglas C.Schmidt <schmidt@cs.wustl.edu>
+// Kirthika Parameswaran <kirthika@cs.wustl.edu>
+// ============================================================================
+
+#ifndef _URL_VISITOR_H
+#define _URL_VISITOR_H
+#include /**/ "ace/pre.h"
+
+#include "ace/Strategies_T.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+#pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+
+#include "HTTP_URL.h"
+#include "Iterators.h"
+#include "ace/Hash_Map_Manager_T.h"
+#include "ace/Caching_Strategies_T.h"
+#include "ace/Cached_Connect_Strategy_T.h"
+#include "Options.h"
+#include "ace/Pair_T.h"
+
+// Forward declarations.
+class URL_Validation_Visitor;
+
+class URL_Processing_Strategy
+{
+ // = TITLE
+ // Abstract base class for the URL processing strategy.
+ //
+ // = DESCRIPTION
+public:
+ URL_Processing_Strategy (URL &,
+ URL_Iterator &);
+ // Constructor.
+
+ virtual ~URL_Processing_Strategy (void);
+
+ virtual int execute (void) = 0;
+ // Perform the strategy.
+
+ virtual int destroy (void);
+
+ // Close down the resources.
+
+protected:
+ URL &url_;
+ // A reference to the URL "context" that we're processing.
+
+ URL_Iterator &iterator_;
+ // Iterator for the URL that we're processing.
+};
+
+class HTTP_Header_Processing_Strategy : public URL_Processing_Strategy
+{
+ // = TITLE
+ // Defines the HTTP header processing strategy.
+ //
+ // = DESCRIPTION
+public:
+ HTTP_Header_Processing_Strategy (URL &,
+ URL_Iterator &);
+ // Constructor.
+
+ virtual int execute (void);
+ // Perform the strategy for processing an HTTP header.
+};
+
+class HTML_Body_Validation_Strategy : public URL_Processing_Strategy
+{
+ // = TITLE
+ // Defines the HTML body processing strategy.
+ //
+ // = DESCRIPTION
+ // This class iterates through the body of an HTML file and
+ // recursively visits embedded links.
+public:
+ HTML_Body_Validation_Strategy (URL &,
+ URL_Iterator &,
+ URL_Validation_Visitor &);
+ // Constructor.
+
+ virtual int execute (void);
+ // Perform the strategy for processing an HTML file. This strategy
+ // iterates over the HTML file and recursively visits embedded links
+ // to process them, as well.
+
+private:
+ URL_Validation_Visitor &visitor_context_;
+ // This is the context of the visit.
+};
+
+class URL_Download_Strategy : public URL_Processing_Strategy
+{
+ // = TITLE
+ // Defines a URL downloading strategy.
+ //
+ // = DESCRIPTION
+ // This class downloads a URL's contents into a temporary file.
+public:
+ URL_Download_Strategy (URL &,
+ URL_Iterator &);
+ // Constructor.
+
+ virtual int execute (void);
+ // Perform the strategy for downloading a URL to a temporary file.
+};
+
+class URL_Visitation_Strategy_Factory
+{
+ // = TITLE
+ // Abstract Factory for the URL visitation strategy.
+ //
+ // = DESCRIPTION
+public:
+ URL_Visitation_Strategy_Factory (URL *);
+
+ /// Destructor.
+ virtual ~URL_Visitation_Strategy_Factory (void);
+
+ // = Factory Methods.
+ virtual URL_Iterator *make_header_iterator (void) = 0;
+ // Factory Method that makes the header iterator.
+
+ virtual URL_Iterator *make_body_iterator (void) = 0;
+ // Factory Method that makes the body iterator.
+
+ virtual URL_Processing_Strategy *make_header_strategy (URL_Iterator &) = 0;
+ // Factory Method that makes the header processing strategy.
+
+ virtual URL_Processing_Strategy *make_body_strategy (URL_Iterator &) = 0;
+ // Factory Method that makes the body processing strategy .
+
+ virtual int destroy (void) = 0;
+ // Close down the resources.
+
+protected:
+ URL *url_;
+ // Stash the URL so we don't have to pass it around.
+};
+
+class URL_Download_Visitation_Strategy_Factory : public URL_Visitation_Strategy_Factory
+{
+ // = TITLE
+ // Concrete Factory for the URL validation visitation strategy.
+ //
+ // = DESCRIPTION
+public:
+ URL_Download_Visitation_Strategy_Factory (URL *);
+ // Constructor.
+
+ // = Factory Methods.
+ virtual URL_Iterator *make_header_iterator (void);
+ // Factory Method that makes an <HTTP_Header_Iterator>.
+
+ virtual URL_Iterator *make_body_iterator (void);
+ // Factory Method that makes an <HTML_Body_Iterator>.
+
+ virtual URL_Processing_Strategy *make_header_strategy (URL_Iterator &);
+ // Factory Method that makes the header processing strategy.
+
+ virtual URL_Processing_Strategy *make_body_strategy (URL_Iterator &);
+ // Factory Method that makes the body processing strategy .
+
+ virtual int destroy (void);
+ // Close down the resources.
+};
+
+class URL_Validation_Visitation_Strategy_Factory : public URL_Visitation_Strategy_Factory
+{
+ // = TITLE
+ // Concrete Factory for the URL validation visitation strategy.
+ //
+ // = DESCRIPTION
+public:
+ URL_Validation_Visitation_Strategy_Factory (URL *,
+ URL_Validation_Visitor &);
+ // Constructor.
+
+ // = Factory Methods.
+ virtual URL_Iterator *make_header_iterator (void);
+ // Factory Method that makes an <HTTP_Header_Iterator>.
+
+ virtual URL_Iterator *make_body_iterator (void);
+ // Factory Method that makes an <HTML_Body_Iterator>.
+
+ virtual URL_Processing_Strategy *make_header_strategy (URL_Iterator &);
+ // Factory Method that makes the header processing strategy.
+
+ virtual URL_Processing_Strategy *make_body_strategy (URL_Iterator &);
+ // Factory Method that makes the body processing strategy .
+
+ virtual int destroy (void);
+ // Close down the resources.
+
+private:
+ URL_Validation_Visitor &visitor_context_;
+ // Context of the visitor.
+};
+
+class URL_Visitor
+{
+ // = TITLE
+ // Base class for the URL Visitor.
+ //
+ // = DESCRIPTION
+ // This class plays the "visitor" role in the Visitor pattern.
+public:
+
+ virtual ~URL_Visitor (void);
+
+ virtual int visit (HTTP_URL &http_url) = 0;
+ // Visit an <HTTP_URL>.
+
+ // @@
+ // virtual int visit (FTP_URL &http_url) = 0;
+
+ virtual int destroy (void) = 0;
+ // Cleanup the resources.
+
+protected:
+ virtual URL_Visitation_Strategy_Factory *make_visitation_strategy_factory (URL &) = 0;
+ // Make the appropriate <URL_Visitation_Strategy_Factory>.
+};
+
+typedef int ATTRIBUTES;
+typedef ACE_Svc_Handler <ACE_SOCK_STREAM, ACE_NULL_SYNCH>
+ Client_Svc_Handler;
+typedef ACE_Pair<Client_Svc_Handler *, ATTRIBUTES>
+ CACHED_HANDLER;
+typedef ACE_Refcounted_Hash_Recyclable<ACE_INET_Addr>
+ ACE_ADDR;
+typedef ACE_Hash<ACE_ADDR> H_KEY;
+typedef ACE_Equal_To<ACE_ADDR> C_KEYS;
+
+typedef ACE_Hash_Map_Manager_Ex<ACE_ADDR, CACHED_HANDLER, H_KEY, C_KEYS, ACE_Null_Mutex>
+ HASH_MAP;
+typedef ACE_Hash_Map_Iterator_Ex<ACE_ADDR, CACHED_HANDLER, H_KEY, C_KEYS, ACE_Null_Mutex>
+ HASH_MAP_ITERATOR;
+typedef ACE_Hash_Map_Reverse_Iterator_Ex<ACE_ADDR, CACHED_HANDLER, H_KEY, C_KEYS, ACE_Null_Mutex>
+ HASH_MAP_REVERSE_ITERATOR;
+
+typedef ACE_Recyclable_Handler_Cleanup_Strategy<ACE_ADDR, CACHED_HANDLER, HASH_MAP>
+ CLEANUP_STRATEGY;
+typedef ACE_Recyclable_Handler_Caching_Utility<ACE_ADDR, CACHED_HANDLER, HASH_MAP, HASH_MAP_ITERATOR, ATTRIBUTES>
+ CACHING_UTILITY;
+
+typedef ACE_LRU_Caching_Strategy<ATTRIBUTES, CACHING_UTILITY>
+ LRU_CACHING_STRATEGY;
+
+typedef LRU_CACHING_STRATEGY
+ CACHING_STRATEGY;
+
+typedef ACE_Strategy_Connector<Client_Svc_Handler, ACE_SOCK_CONNECTOR>
+ STRATEGY_CONNECTOR;
+
+typedef ACE_NOOP_Creation_Strategy<Client_Svc_Handler>
+ NULL_CREATION_STRATEGY;
+
+typedef ACE_NOOP_Concurrency_Strategy<Client_Svc_Handler>
+ NULL_ACTIVATION_STRATEGY;
+
+typedef ACE_Cached_Connect_Strategy_Ex<Client_Svc_Handler, ACE_SOCK_CONNECTOR, CACHING_STRATEGY, ATTRIBUTES, ACE_SYNCH_NULL_MUTEX>
+ CACHED_CONNECT_STRATEGY;
+
+class URL_Validation_Visitor : public URL_Visitor
+{
+ // = TITLE
+ // Subclass that defines the URL validation visitor.
+ //
+ // = DESCRIPTION
+ // This class checks to make sure that the <HTTP_URL> is valid.
+ // If the <HTTP_URL> is an <HTML> file, it can also be used to
+ // recursively check that all embedded links in this file are
+ // valid.
+public:
+ typedef ACE_Hash_Map_Manager <ACE_URL_Addr, URL_Status, ACE_Null_Mutex>
+ URL_CACHE;
+
+ virtual int visit (HTTP_URL &http_url);
+ // Visit an <HTTP_URL> to make sure that it's valid. If the content
+ // type of the <HTTP_URL> is "text/html" and the <recursion> option
+ // is enabled then <visit> recursively checks each link embedded in
+ // the HTML page.
+
+ // @@
+ // virtual int visit (FTP_URL &http_url);
+
+ URL_Validation_Visitor (void);
+ virtual int destroy (void);
+ // Cleanup the resources.
+
+ URL_CACHE &url_cache (void);
+ // Returns a reference to the URL cache.
+
+
+ /*
+
+
+ typedef ACE_Svc_Handler<ACE_SOCK_STREAM, ACE_NULL_SYNCH>
+ Svc_Handler;
+ typedef ACE_Strategy_Connector<Svc_Handler, ACE_SOCK_CONNECTOR>
+ STRAT_CONNECTOR;
+ typedef ACE_Refcounted_Hash_Recyclable<ACE_INET_Addr>
+ REFCOUNTED_HASH_RECYCLABLE_ADDRESS;
+ typedef ACE_NOOP_Creation_Strategy<Svc_Handler>
+ NULL_CREATION_STRATEGY;
+ typedef ACE_NOOP_Concurrency_Strategy<Svc_Handler>
+ NULL_ACTIVATION_STRATEGY;
+
+ typedef ACE_Hash_Map_Manager_Ex<REFCOUNTED_HASH_RECYCLABLE_ADDRESS,\
+ ACE_Pair<Svc_Handler *, int>,\
+ ACE_Hash<REFCOUNTED_HASH_RECYCLABLE_ADDRESS>, \
+ ACE_Equal_To<REFCOUNTED_HASH_RECYCLABLE_ADDRESS>,\
+ ACE_Null_Mutex>
+ CONNECTION_HASH_MAP;
+ typedef ACE_Hash_Map_Iterator_Ex<REFCOUNTED_HASH_RECYCLABLE_ADDRESS,\
+ ACE_Pair<Svc_Handler *, int>,\
+ ACE_Hash<REFCOUNTED_HASH_RECYCLABLE_ADDRESS>, \
+ ACE_Equal_To<REFCOUNTED_HASH_RECYCLABLE_ADDRESS>,\
+ ACE_Null_Mutex>
+ CONNECTION_HASH_MAP_ITERATOR;
+ typedef ACE_Hash_Map_Reverse_Iterator_Ex<REFCOUNTED_HASH_RECYCLABLE_ADDRESS,\
+ ACE_Pair<Svc_Handler *, int>,\
+ ACE_Hash<REFCOUNTED_HASH_RECYCLABLE_ADDRESS>, \
+ ACE_Equal_To<REFCOUNTED_HASH_RECYCLABLE_ADDRESS>,\
+ ACE_Null_Mutex>
+ CONNECTION_HASH_MAP_REVERSE_ITERATOR;
+ typedef ACE_Pair_Caching_Utility <REFCOUNTED_HASH_RECYCLABLE_ADDRESS, \
+ ACE_Pair<Svc_Handler *, int>, \
+ CONNECTION_HASH_MAP, CONNECTION_HASH_MAP_ITERATOR, int >
+ CACHING_STRATEGY_UTILITY;
+ typedef ACE_LRU_Caching_Strategy<REFCOUNTED_HASH_RECYCLABLE_ADDRESS,\
+ ACE_Pair<Svc_Handler *, int>,\
+ CONNECTION_HASH_MAP, int,\
+ CACHING_STRATEGY_UTILITY >
+ LRU;
+ typedef ACE_Cached_Connect_Strategy_Ex<Svc_Handler,ACE_SOCK_CONNECTOR, LRU,int, ACE_SYNCH_NULL_MUTEX>
+ CACHED_CONNECT_STRATEGY;
+ */
+protected:
+ virtual ~URL_Validation_Visitor (void);
+ virtual URL_Visitation_Strategy_Factory *make_visitation_strategy_factory (URL &);
+ // Factory Method that makes a
+ // <URL_Validation_Visitation_Strategy_Factory>.
+
+ URL_CACHE url_cache_;
+ // Cache the status of URLs we've already validated.
+
+ int in_cache (const ACE_URL_Addr &url_addr);
+ // Check to see if the reply status of this <url_addr> is in the
+ // cache. Returns 1 if so, 0 if not.
+
+ NULL_CREATION_STRATEGY creation_strategy_;
+ NULL_ACTIVATION_STRATEGY activation_strategy_;
+
+ // Configure the Strategy Connector with a strategy that caches
+ // connection.
+ CACHED_CONNECT_STRATEGY *caching_connect_strategy_;
+
+ STRATEGY_CONNECTOR *strat_connector_;
+
+ CACHING_STRATEGY caching_strategy_;
+};
+
+
+class URL_Download_Visitor : public URL_Visitor
+{
+ // = TITLE
+ // Subclass for the URL validtion visitor.
+ //
+ // = DESCRIPTION
+ // This class checks to make sure that the <HTTP_URL> is valid.
+public:
+ virtual int visit (HTTP_URL &http_url);
+ // Visit an <HTTP_URL> to make sure that it's valid. If the content
+ // type of the <HTTP_URL> is "text/html" and the <recursion> option
+ // is enabled then <visit> recursively checks each link embedded in
+ // the HTML page.
+
+ // @@
+ // virtual int visit (FTP_URL &http_url);
+
+ virtual int destroy (void);
+ // Cleanup the resources.
+
+protected:
+ URL_Visitation_Strategy_Factory *make_visitation_strategy_factory (URL &);
+ // Factory Method that makes a <URL_Download_Visitation_Strategy_Factory>.
+};
+
+template <class T>
+class Auto_Destroyer
+{
+ // = TITLE
+ // Simple class that ensures the <destroy> method is called on our
+ // <URL_*> objects when they go out of scope.
+ //
+ // = DESCRIPTION
+ // This class is similar to an auto_ptr<> and should be used to
+ // simplify blocks of code that must create/destroy pointers to
+ // various <URL_*> related strategies and iterators.
+public:
+ Auto_Destroyer (T *t): t_ (t) {}
+ T *operator-> (void) { return this->t_; }
+ T *operator *(void) { return this->t_; }
+ void operator= (T *t)
+ {
+ if (this->t_ != 0)
+ this->t_->destroy ();
+ this->t_ = t;
+ }
+ ~Auto_Destroyer (void)
+ {
+ if (this->t_ != 0)
+ t_->destroy ();
+ }
+private:
+ T *t_;
+};
+
+#include /**/ "ace/post.h"
+#endif /* _URL_VISITOR_H */
diff --git a/ACE/examples/Web_Crawler/URL_Visitor_Factory.cpp b/ACE/examples/Web_Crawler/URL_Visitor_Factory.cpp
new file mode 100644
index 00000000000..1b8a316b219
--- /dev/null
+++ b/ACE/examples/Web_Crawler/URL_Visitor_Factory.cpp
@@ -0,0 +1,53 @@
+/* -*- C++ -*- */
+// $Id$
+
+#include "URL_Visitor_Factory.h"
+
+ACE_RCSID (Web_Crawler,
+ URL_Visitor_Factory,
+ "$Id$")
+
+
+URL_Visitor_Factory::~URL_Visitor_Factory (void)
+{
+}
+
+URL_Visitor *
+URL_Validation_Visitor_Factory::make_visitor (void)
+{
+ URL_Visitor *v;
+
+ ACE_NEW_RETURN (v,
+ URL_Validation_Visitor,
+ 0);
+
+ return v;
+}
+
+Command_Processor *
+URL_Validation_Visitor_Factory::make_command_processor (void)
+{
+ Command_Processor *cp;
+
+ ACE_NEW_RETURN (cp,
+ Command_Processor,
+ 0);
+ return cp;
+}
+
+URL_Visitor *
+URL_Download_Visitor_Factory::make_visitor (void)
+{
+ URL_Visitor *v;
+
+ ACE_NEW_RETURN (v,
+ URL_Download_Visitor,
+ 0);
+ return v;
+}
+
+Command_Processor *
+URL_Download_Visitor_Factory::make_command_processor (void)
+{
+ return 0;
+}
diff --git a/ACE/examples/Web_Crawler/URL_Visitor_Factory.h b/ACE/examples/Web_Crawler/URL_Visitor_Factory.h
new file mode 100644
index 00000000000..9f484afe9f0
--- /dev/null
+++ b/ACE/examples/Web_Crawler/URL_Visitor_Factory.h
@@ -0,0 +1,74 @@
+/* -*- C++ -*- */
+// $Id$
+
+// ============================================================================
+//
+// = LIBRARY
+// examples/Web_Crawler
+//
+// = FILENAME
+// URL_Visitor_Factory.h
+//
+// = AUTHOR
+// Douglas C. Schmidt <schmidt@cs.wustl.edu>
+//
+// ============================================================================
+
+#ifndef _URL_VISITOR_FACTORY_H
+#define _URL_VISITOR_FACTORY_H
+
+#include "URL_Visitor.h"
+#include "Command_Processor.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+#pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+class URL_Visitor_Factory
+{
+ // = TITLE
+ // Abstract base class that creates URL visitors.
+ //
+ // = DESCRIPTION
+ // Subclasses define each of the Factory Methods to
+ // make the right objects, which all "vary" together.
+public:
+
+ /// Destructor.
+ virtual ~URL_Visitor_Factory (void);
+
+ virtual URL_Visitor *make_visitor (void) = 0;
+ // Factory Method that makes the appropriate type of <URL_Visitor>.
+
+ virtual Command_Processor *make_command_processor (void) = 0;
+ // Factory Method that makes the appropriate type of
+ // <Command_Processor>.
+};
+
+class URL_Validation_Visitor_Factory : public URL_Visitor_Factory
+{
+ // = TITLE
+ // Create a URL visitor that validates URL links.
+public:
+ virtual URL_Visitor *make_visitor (void);
+ // Factory Method that makes a <URL_Validation_Visitor>.
+
+ virtual Command_Processor *make_command_processor (void);
+ // Factory Method that makes a <FIFO_Command_Processor>.
+
+
+};
+
+class URL_Download_Visitor_Factory : public URL_Visitor_Factory
+{
+ // = TITLE
+ // Create a URL visitor that downloads URL links.
+public:
+ virtual URL_Visitor *make_visitor (void);
+ // Factory Method that makes a <URL_Download_Visitor>.
+
+ virtual Command_Processor *make_command_processor (void);
+ // Factory Method that makes a <FIFO_Command_Processor>.
+};
+
+#endif /* _URL_VISITOR_FACTORY_H */
diff --git a/ACE/examples/Web_Crawler/Web_Crawler.cpp b/ACE/examples/Web_Crawler/Web_Crawler.cpp
new file mode 100644
index 00000000000..16639a38d73
--- /dev/null
+++ b/ACE/examples/Web_Crawler/Web_Crawler.cpp
@@ -0,0 +1,95 @@
+// $Id$
+
+#include "Options.h"
+#include "URL_Visitor_Factory.h"
+#include "Web_Crawler.h"
+
+ACE_RCSID(Web_Crawler, Web_Crawler, "$Id$")
+
+Web_Crawler::~Web_Crawler (void)
+{
+ delete this->url_visitor_factory_;
+}
+
+Web_Crawler::Web_Crawler (void)
+ : url_visitor_factory_ (0)
+{
+}
+
+int
+Web_Crawler::open (int argc, ACE_TCHAR *argv[])
+{
+ if (OPTIONS::instance ()->parse_args (argc, argv) == -1)
+ return -1;
+ // @@ Put the ACE_Service_Config::open() stuff here somewhere...
+ else
+ {
+ // For now just hardcode this to create "validation" visitors.
+ ACE_NEW_RETURN (this->url_visitor_factory_,
+ URL_Validation_Visitor_Factory,
+ -1);
+ return 0;
+ }
+}
+
+int
+Web_Crawler::run (void)
+{
+ // Make the appropriate <URL_Visitor>.
+ Auto_Destroyer<URL_Visitor> visitor (this->url_visitor_factory_->make_visitor ());
+
+ if (*visitor == 0)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%p\n",
+ "make_visitor"),
+ -1);
+
+ // Make the appropriate <Command_Processor>.
+ Auto_Destroyer<Command_Processor> cp (this->url_visitor_factory_->make_command_processor ());
+
+ if (*cp == 0)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%p\n",
+ "make_command_processor"),
+ -1);
+
+ // Set the <Command_Processor> in the <Options> to make it visible.
+ OPTIONS::instance ()->command_processor (*cp);
+
+ // Set the <URL_Visitor> in the <Options> to make it visible.
+ OPTIONS::instance ()->visitor (*visitor);
+
+ // @@ You fill in here...
+ ACE_URL_Addr *url_addr;
+ ACE_NEW_RETURN (url_addr,
+ ACE_URL_Addr (OPTIONS::instance()->hostname (),
+ OPTIONS::instance()->path_name (),
+ OPTIONS::instance()->port_no ()), //KIRTHIKA
+ 0);
+ Auto_Destroyer<ACE_URL_Addr> url_addr_ptr (url_addr);
+
+ HTTP_URL *http_url;
+ ACE_NEW_RETURN (http_url,
+ HTTP_URL (**url_addr_ptr),
+ 0);
+
+ Auto_Destroyer<HTTP_URL> http_url_ptr (http_url);
+
+ URL_Command *url_command;
+ ACE_NEW_RETURN (url_command,
+ URL_Command (*http_url_ptr),
+ 0);
+ // Auto_Destroyer<URL_Command> url_command_ptr (url_command);
+
+ if (cp->insert (url_command) != 0)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%p\n", "insert"),
+ -1);
+
+ if (cp->execute () != 0)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%p\n", "execute"),
+ -1);
+ return 0;
+}
+
diff --git a/ACE/examples/Web_Crawler/Web_Crawler.h b/ACE/examples/Web_Crawler/Web_Crawler.h
new file mode 100644
index 00000000000..01e275e2187
--- /dev/null
+++ b/ACE/examples/Web_Crawler/Web_Crawler.h
@@ -0,0 +1,62 @@
+/* -*- C++ -*- */
+// $Id$
+
+// ============================================================================
+//
+// = LIBRARY
+// examples/Web_Crawler
+//
+// = FILENAME
+// Web_Crawler.h
+//
+// = AUTHOR
+// Douglas C. Schmidt <schmidt@cs.wustl.edu>
+//
+// ============================================================================
+
+#ifndef _WEB_CRAWLER_H
+#define _WEB_CRAWLER_H
+
+#include "URL_Addr.h"
+#include "HTTP_URL.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+#pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+// Forward declaration.
+class URL_Visitor_Factory;
+
+class Web_Crawler
+{
+ // = TITLE
+ // An abstraction for a Web Crawler.
+ //
+ // = DESCRIPTION
+ // This class is a Facade that organizes the other classes in the
+ // solution, which include a factory that creates a visitor,
+ // which in turn embodies the appropriate visitation strategy.
+public:
+ // = Initialization and termination methods.
+ Web_Crawler (void);
+ // Constructor.
+
+ ~Web_Crawler (void);
+ // Destructor.
+
+ int open (int argc, ACE_TCHAR *argv[]);
+ // Parses the command-line options and initializes the
+ // <URL_Visitor_Factory>.
+
+ int run (void);
+ // Run the Web Crawler and carries out whatever visitation strategy
+ // is configured. Returns -1 on failure and 0 on success.
+
+private:
+ URL_Visitor_Factory *url_visitor_factory_;
+ // Pointer to a factory that creates visitors that explore URLs and
+ // perform various tasks. Subclasses of <URL_Visitor_Factory>
+ // determine what happens during a visitation.
+};
+
+#endif /* _WEB_CRAWLER_H */
diff --git a/ACE/examples/Web_Crawler/Web_Crawler.mpc b/ACE/examples/Web_Crawler/Web_Crawler.mpc
new file mode 100644
index 00000000000..7750d7cbd5d
--- /dev/null
+++ b/ACE/examples/Web_Crawler/Web_Crawler.mpc
@@ -0,0 +1,7 @@
+// -*- MPC -*-
+// $Id$
+
+project : aceexe {
+ avoids += ace_for_tao
+ exename = main
+}
diff --git a/ACE/examples/Web_Crawler/main.cpp b/ACE/examples/Web_Crawler/main.cpp
new file mode 100644
index 00000000000..1735f811b78
--- /dev/null
+++ b/ACE/examples/Web_Crawler/main.cpp
@@ -0,0 +1,51 @@
+// $Id$
+
+// ============================================================================
+//
+// = LIBRARY
+// examples/Web_Crawler
+//
+// = FILENAME
+// main.cpp
+//
+// = DESCRIPTION
+// This program implements a Web crawler that can be configured to
+// apply various strategies to URLs that it visits.
+//
+// = AUTHOR
+// Doug Schmidt <schmidt@cs.wustl.edu>
+//
+// ============================================================================
+
+#include "ace/OS_main.h"
+#include "ace/Signal.h"
+#include "Web_Crawler.h"
+#include "Options.h"
+
+ACE_RCSID(Web_Crawler, main, "$Id$")
+
+void sig_handler (int)
+{
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("aborting!\n")));
+ ACE_OS::abort ();
+}
+
+int
+ACE_TMAIN (int argc, ACE_TCHAR *argv[])
+{
+#if !defined (ACE_HAS_WINCE)
+ ACE_Sig_Action sa ((ACE_SignalHandler) sig_handler, SIGFPE);
+#endif
+ Web_Crawler crawler;
+
+ if (crawler.open (argc, argv) == -1)
+ return 1;
+ else if (crawler.run () == -1)
+ return 1;
+ else
+ return 0;
+}
+
+
+
diff --git a/ACE/examples/example_base.mpb b/ACE/examples/example_base.mpb
new file mode 100644
index 00000000000..71b8b3452c6
--- /dev/null
+++ b/ACE/examples/example_base.mpb
@@ -0,0 +1,8 @@
+// -*- MPC -*-
+// $Id$
+
+// Anything specific to examples could be added here.
+// examples.mwc uses the implicit keyword to cause this
+// project to be used as the base for all examples,
+project : aceexe {
+} \ No newline at end of file
diff --git a/ACE/examples/examples.mwc b/ACE/examples/examples.mwc
new file mode 100644
index 00000000000..975ad4e462d
--- /dev/null
+++ b/ACE/examples/examples.mwc
@@ -0,0 +1,14 @@
+// -*- MPC -*-
+// $Id$
+
+workspace {
+ // This doesn't work quite yet, because not all the projects
+ // can be created implicitly. To fix this, we can either create
+ // a separate directory for each separate project, or we can
+ // add mpc files for C++NPv1/2 and other problem directories.
+ // The nice thing about splitting up into separate directories is
+ // that it completely eliminates mpc maintenance.
+
+ implicit = example_base
+ cmdline += -include $PWD
+}