1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
|
// **********************************************************************
//
// Copyright (c) 2003-2017 ZeroC, Inc. All rights reserved.
//
// This copy of Ice is licensed to you under the terms described in the
// ICE_LICENSE file included in this distribution.
//
// **********************************************************************
#ifndef ICE_APPLICATION_H
#define ICE_APPLICATION_H
#include <Ice/Initialize.h>
#include <IceUtil/Mutex.h>
#include <IceUtil/Cond.h>
namespace Ice
{
#ifdef ICE_CPP11_MAPPING
enum class SignalPolicy : unsigned char
#else
enum SignalPolicy
#endif
{ HandleSignals, NoSignalHandling };
class ICE_API Application : private IceUtil::noncopyable
{
public:
Application(SignalPolicy = ICE_ENUM(SignalPolicy, HandleSignals));
virtual ~Application();
//
// This main() must be called by the global main(). main()
// initializes the Communicator, calls run() as a template method,
// and destroys the Communicator upon return from run(). It
// thereby handles all exceptions properly, i.e., error messages
// are printed if exceptions propagate to main(), and the
// Communicator is always destroyed, regardless of exceptions.
//
int main(int, char*[], const Ice::InitializationData& = Ice::InitializationData());
int main(int, char*[], const char*);
int main(int, char* const [], const Ice::InitializationData& = Ice::InitializationData());
int main(int, char* const [], const char*);
#ifdef _WIN32
int main(int, wchar_t*[], const Ice::InitializationData& = Ice::InitializationData());
int main(int, wchar_t*[], const char*);
#endif
int main(const StringSeq&, const Ice::InitializationData& = Ice::InitializationData());
int main(const StringSeq&, const char*);
virtual int run(int, char*[]) = 0;
//
// Override this to provide a custom application interrupt
// hook. You must call callbackOnInterrupt for this method to
// be called. Note that the interruptCallback can be called
// concurrently with any other thread (including main) in your
// application and thus must take appropriate concurrency
// precautions.
//
virtual void interruptCallback(int);
//
// Return the application name, i.e., argv[0].
//
static const char* appName();
//
// One limitation of this class is that there can only be one
// Application instance, with one global Communicator, accessible
// with this communicator() operation. This limitation is due to
// how the signal handling functions below operate. If you require
// multiple Communicators, then you cannot use this Application
// framework class.
//
static CommunicatorPtr communicator();
//
// These methods can be used to set a Ctrl+C Handler callback.
//
static void destroyOnInterrupt();
static void shutdownOnInterrupt();
static void ignoreInterrupt();
static void callbackOnInterrupt();
//
// These methods can be used to temporarily block a signal and
// arrange for delivery of a pending signal later. Any signal that
// is received after holdInterrupt() was called is remembered and
// delivered when releaseInterupt() is called. That signal is then
// handled according to the signal disposition established with
// destroyOnInterrupt(), shutdownOnInterrupt() or
// ignoreInterrupt().
//
static void holdInterrupt();
static void releaseInterrupt();
//
// This method returns true if a signal handler was triggered,
// false otherwise. This can be used once
// Communicator::waitForShutdown() returns to test whether the
// shutdown was due to an interrupt (interrupted() returns true in
// that case) or because Communicator::shutdown() was called
// (interrupted() returns false in that case).
//
static bool interrupted();
protected:
virtual int doMain(int, char*[], const Ice::InitializationData&);
//
// _mutex and _condVar are used to synchronize the main thread and
// the CtrlCHandler thread
//
static IceUtil::Mutex _mutex;
static IceUtil::Cond _condVar;
//
// Variables than can change while run() and communicator->destroy() are running!
//
static bool _callbackInProgress;
static bool _destroyed;
static bool _interrupted;
//
// Variables that are immutable during run() and until communicator->destroy() has returned;
// before and after run(), and once communicator->destroy() has returned, we assume that
// only the main thread and CtrlCHandler threads are running.
//
static std::string _appName;
static Ice::CommunicatorPtr _communicator;
static Ice::SignalPolicy _signalPolicy;
static Ice::Application* _application;
private:
static void holdInterruptCallback(int);
static void destroyOnInterruptCallback(int);
static void shutdownOnInterruptCallback(int);
static void callbackOnInterruptCallback(int);
};
}
#endif
|