source: nscp/trunk/include/thread.h @ 7da80b5

Last change on this file since 7da80b5 was 7da80b5, checked in by Michael Medin <michael@…>, 8 years ago

2005-05-23 MickeM

+ Added obfuscated password support
+ Added some more debug info on commands (returncode, and input args)
+ Added some more comments ot the NSC.ini
+ Added central password "override"
+ Added central "host override"
+ Fixed bug with external commands always getting WARNING state

2005-05-22 MickeM

+ Added debug outout for command
+ Added timestamps for log-to-file (date_mask to configure format)
+ Added support for "no password" with check_nt
+ Added log of bad password on NSClient requests.

  • Some threading issues fixed (I hate threading :)
  • Property mode set to 100644
File size: 5.7 KB
Line 
1#pragma once
2
3#include <process.h>
4#include <Mutex.h>
5
6class ThreadException {
7public:
8        std::string e_;
9        ThreadException(std::string e) : e_(e) {
10                std::cout << e << std::endl;
11        }
12};
13
14/**
15 * @ingroup NSClientCompat
16 * Thread helper class.
17 * This class wraps another class inside it and makes that class run in the background as a working thread.
18 * Notice that no threading issues are handled so you are on your own when it comes to that.
19 * This simply wraps some API function inside a pretty interface.
20 *
21 * @version 1.0
22 * first version
23 *
24 * @date 02-13-2005
25 *
26 * @author mickem
27 *
28 * @par license
29 * This code is absolutely free to use and modify. The code is provided "as is" with
30 * no expressed or implied warranty. The author accepts no liability if it causes
31 * any damage to your computer, causes your pet to fall ill, increases baldness
32 * or makes your car start emitting strange noises when you start it up.
33 * This code has no bugs, just undocumented features!
34 *
35 * @todo Make this class (or another) handle multiple instances of the thread ?
36 */
37template <class T>
38class Thread {
39private:
40        HANDLE hThread_;                // Thread handle
41        T* pObject_;                    // Wrapped object
42        HANDLE hStopEvent_;             // Event to signal that the thread has stopped
43        HANDLE hMutex_;                 // Mutex to protect internal data
44
45
46        typedef struct thread_param {
47                HANDLE hStopEvent;      // The stop event to signal when thread dies
48                T *instance;            // The thread instance object
49                LPVOID lpParam;         // The optional argument to the thread
50                Thread *pCore;
51        } thread_param;
52
53public:
54        /**
55         * Default c-tor.
56         * Sets up default values
57         */
58        Thread() : hThread_(NULL), pObject_(NULL), hStopEvent_(NULL) {
59                hMutex_ = CreateMutex(NULL, FALSE, NULL);
60                assert(hMutex_ != NULL);
61        }
62        /**
63         * Default d-tor.
64         * Does not really kill the thread only closes the handle to it.
65         *  @bug Should perhaps kill the thread, delete the object etc ?
66         */
67        virtual ~Thread() {
68                {
69                        MutexLock mutex(hMutex_, 5000L);
70                        if (!mutex.hasMutex()) {
71                                throw ThreadException("Could not retrieve mutex when killing thread, we are fucked...");
72                        }
73                        hThread_ = NULL;
74                        if (hStopEvent_)
75                                CloseHandle(hStopEvent_);
76                        hStopEvent_ = NULL;
77                        delete pObject_;
78                        pObject_ = NULL;
79                }
80                if (hMutex_)
81                        CloseHandle(hMutex_);
82                hMutex_ = NULL;
83        }
84
85private:
86        /**
87         * Static thread instance (this is the real thread procedure that wraps the internal objects)
88         * This function will wait for <b>nice</b> termination of the process so if that does not happen the thread canoot quit.
89         *
90         * @param lpParameter thread_param* with arguments for the thread construction
91         * @return exit status
92         */
93        static void threadProc(LPVOID lpParameter) {
94                thread_param* param = static_cast<thread_param*>(lpParameter);
95                T* instance = param->instance;
96                HANDLE hStopEvent = param->hStopEvent;
97                LPVOID lpParam = param->lpParam;
98                Thread *pCore = param->pCore;
99                delete param;
100
101                instance->threadProc(lpParam);
102                pCore->terminate();
103                SetEvent(hStopEvent);
104                _endthread();
105        }
106
107public:
108        /**
109         * Create a thread and possibly send a parameter to it.
110         * If a thread has already been create this function will throw an exception
111         * <b>NOTICE</b> The object returned is managed inside this object so it is not very safe to use it.
112         *
113         * @param lpParam An argument to the thread
114         * @return An instance of the thread object.
115         * @bug the object return thing is *unsafe* and should be changed (if the thread is terminated that pointer is invalidated without any signal).
116         */
117        void createThread(LPVOID lpParam = NULL) {
118                thread_param* param = NULL;
119                {
120                        MutexLock mutex(hMutex_, 5000L);
121                        if (!mutex.hasMutex()) {
122                                throw ThreadException("Could not retrieve mutex, thread not started...");
123                        }
124                        if (pObject_) {
125                                throw ThreadException("Thread already started, thread not started...");
126                        }
127                        assert(hStopEvent_ == NULL);
128                        param = new thread_param;
129                        param->instance = pObject_ = new T;
130                        param->hStopEvent = hStopEvent_ = CreateEvent(NULL, TRUE, FALSE, NULL);
131                        param->lpParam = lpParam;
132                        param->pCore = this;
133                }
134                hThread_ = reinterpret_cast<HANDLE>(::_beginthread(threadProc, 0, reinterpret_cast<VOID*>(param)));
135        }
136        /**
137         * Ask the thread to terminate (within 5 seconds) if not return false.
138         * @param delay The time to wait for the thread
139         * @return true if the thread has terminated
140         */
141        bool exitThread(const unsigned int delay = 5000L) {
142                DWORD dwWaitResult = -1;
143                {
144                        MutexLock mutex(hMutex_, 5000L);
145                        if (!mutex.hasMutex()) {
146                                throw ThreadException("Could not retrieve mutex, thread not stopped...");
147                        }
148                        if (!pObject_)
149                                return true;
150                        assert(hStopEvent_ != NULL);
151                        pObject_->exitThread();
152                }
153                dwWaitResult = WaitForSingleObject(hStopEvent_, delay);
154                switch (dwWaitResult) {
155                        // The thread got mutex ownership.
156                        case WAIT_OBJECT_0:
157                                return true;
158                                // Did not get a signal due to time-out.
159                        case WAIT_TIMEOUT:
160                                return false;
161                                // Never got a signal.
162                        case WAIT_ABANDONED:
163                                return false;
164                }
165                return false;
166        }
167        bool hasActiveThread() const {
168                MutexLock mutex(hMutex_, 5000L);
169                if (!mutex.hasMutex()) {
170                        throw ThreadException("Could not retrieve mutex, thread not stopped...");
171                }
172                return pObject_ != NULL;
173        }
174        const T* getThreadConst() const {
175                MutexLock mutex(hMutex_, 5000L);
176                if (!mutex.hasMutex()) {
177                        throw ThreadException("Could not retrieve mutex, thread not stopped...");
178                }
179                return pObject_;
180        }
181        T* getThread() {
182                MutexLock mutex(hMutex_, 5000L);
183                if (!mutex.hasMutex()) {
184                        throw ThreadException("Could not retrieve mutex, thread not stopped...");
185                }
186                return pObject_;
187        }
188private:
189        void terminate() {
190                MutexLock mutex(hMutex_, 5000L);
191                if (!mutex.hasMutex()) {
192                        throw ThreadException("Could not retrieve mutex, thread not stopped...");
193                }
194                delete pObject_;
195                pObject_ = NULL;
196                hThread_ = NULL;
197        }
198};
199
Note: See TracBrowser for help on using the repository browser.