Poller::Slot &slot=poller_->add_pollable(obj, events);
// Interrupt a possible poll in progress
- pthread_kill(main_tid, SIGALRM);
+#ifndef WIN32 //XXX
+ pthread_kill(main_tid, SIGALRM);
+#endif
return slot;
}
return 126;
}
+#ifndef WIN32 //XXX
signal(SIGALRM, &sigalrm_);
+#endif
try
{
cerr<<"The programmer was lazy and didn't write a usage() function for this application.\n";
}
+Application::Application():
+ exit_code(0),
+ tick_mode_(IDLE),
+ poller_(0),
+ ev_mgr_(0)
+#ifndef WIN32
+ //XXX Figure out how to get the current thread on win32
+ ,main_tid(pthread_self())
+#endif
+{ }
+
/**
Default main loop. Calls tick() periodically if do_ticks is true, otherwise
just sleeps. A custom main loop should monitor the done member variable and
if(poller_)
poller_->poll(0);
tick();
+#ifdef WIN32
+ Sleep(0);
+#else
sched_yield();
+#endif
}
else
{
void Application::set_tick_mode(TickMode t)
{
tick_mode_=t;
+#ifndef WIN32 //XXX
pthread_kill(main_tid, SIGALRM);
+#endif
}
/**
{
done=true;
exit_code=c;
+#ifndef WIN32 //XXX
pthread_kill(main_tid, SIGALRM);
+#endif
}
void Application::sighandler_(int s)
#ifndef MSP_FRAMEWORK_APPLICATION_H_
#define MSP_FRAMEWORK_APPLICATION_H_
-#ifdef WIN32
-#include "win32signum.h"
-#endif
-
-#include <pthread.h>
#include "event.h"
#include "poller.h"
+#include "types.h"
namespace Msp {
bool done;
int exit_code;
- Application(): exit_code(0), tick_mode_(IDLE), poller_(0), ev_mgr_(0), main_tid(pthread_self()) { }
+ Application();
virtual int main();
void catch_signal(int);
void set_tick_mode(TickMode);
TickMode tick_mode_;
Poller *poller_;
EventManager *ev_mgr_;
- pthread_t main_tid;
+ ThreadHandle main_tid;
Application(const Application &);
Application &operator=(const Application &);
#ifndef MSP_FRAMEWORK_MUTEX_H_
#define MSP_FRAMEWORK_MUTEX_H_
-#include <pthread.h>
#include <msp/refcount.h>
+#include "types.h"
namespace Msp {
class Mutex
{
public:
+#ifndef WIN32
Mutex() { pthread_mutex_init(&mutex, 0); }
int lock() { return pthread_mutex_lock(&mutex); }
int trylock() { return pthread_mutex_trylock(&mutex); }
int unlock() { return pthread_mutex_unlock(&mutex); }
~Mutex() { pthread_mutex_destroy(&mutex); }
+#else
+ Mutex() { mutex=CreateMutex(0, false, 0); }
+ int lock() { return WaitForSingleObject(mutex, INFINITE)==WAIT_OBJECT_0; }
+ int trylock() { return WaitForSingleObject(mutex, 0)==WAIT_OBJECT_0; }
+ int unlock() { return !ReleaseMutex(mutex); }
+ ~Mutex() { CloseHandle(mutex); }
+#endif
private:
- pthread_mutex_t mutex;
+ MutexHandle mutex;
friend class Semaphore;
};
return 0;
#else
pollfd pfd={get_fd(), events, 0};
- int result=select(&pfd, 1, timeout);
int result=::poll(&pfd, 1, timeout);
if(result<=0)
return result;
Copyright © 2006 Mikko Rasa, Mikkosoft Productions
Distributed under the LGPL
*/
+#ifndef WIN32
#include <signal.h>
+#endif
#include "thread.h"
namespace Msp {
-void *Thread::join()
+/**
+Waits for the thread to exit. Calling this from the thread will cause a
+deadlock.
+*/
+void Thread::join()
{
- if(!valid_)
- return 0;
+ if(!launched_)
+ return;
- void *result;
- pthread_join(thread_, &result);
- valid_=false;
- return result;
+#ifdef WIN32
+ WaitForSingleObject(thread_, INFINITE);
+#else
+ pthread_join(thread_, 0);
+#endif
+ launched_=false;
+}
+
+/**
+Requests the thread to terminate gracefully. Currently unimplemented on win32.
+*/
+void Thread::cancel()
+{
+#ifndef WIN32 //XXX
+ pthread_cancel(thread_);
+#endif
+}
+
+/**
+Violently terminates the thread.
+*/
+void Thread::kill()
+{
+#ifdef WIN32
+ TerminateThread(thread_, 0);
+#else
+ pthread_kill(thread_, SIGKILL);
+#endif
}
Thread::~Thread()
{
- if(valid_)
- kill(SIGKILL);
+ if(launched_)
+ kill();
+}
+
+void Thread::launch()
+{
+ if(launched_)
+ return;
+
+#ifdef WIN32
+ DWORD dummy; // Win9x needs the lpTthreadId parameter
+ thread_=CreateThread(0, 0, &main_, this, 0, &dummy);
+#else
+ pthread_create(&thread_, 0, &main_, this);
+#endif
+ launched_=true;
}
} // namespace Msp
#ifndef MSP_FRAMEWORK_THREAD_H_
#define MSP_FRAMEWORK_THREAD_H_
-#ifdef WIN32
-#include "win32signum.h"
-#endif
-
-#include <pthread.h>
+#include "types.h"
namespace Msp {
+/**
+Base class for threads. To create a thread for some task, derive it from this
+class and implement the main() function. Note that threads are not
+automatically started upon creation - you must manually call launch() instead.
+This is to allow initializing variables of the derived class before the thread
+is started.
+*/
class Thread
{
public:
- void *join();
- void kill(int s) { pthread_kill(thread_, s); }
+ void join();
+ void cancel();
+ void kill();
virtual ~Thread();
protected:
- Thread(): valid_(false) { }
- void launch() { if(!valid_) pthread_create(&thread_, 0, &main_, this); }
- virtual void *main()=0;
- void exit(void *r) { pthread_exit(r); }
+ Thread(): launched_(false) { }
+ void launch();
+ virtual void main()=0;
+ void check_cancel();
private:
- pthread_t thread_;
- bool valid_;
+ ThreadHandle thread_;
+ bool launched_;
Thread(const Thread &);
Thread &operator=(const Thread &);
- static void *main_(void *t) { return ((Thread *)t)->main(); }
+#ifdef WIN32
+# define THREAD_RETURN_ DWORD WINAPI
+#else
+# define THREAD_RETURN_ void *
+#endif
+ static THREAD_RETURN_ main_(void *t) { ((Thread *)t)->main(); return 0; }
+#undef THREAD_RETURN_
};
} // namespace Msp
--- /dev/null
+/*
+This file is part of libmspframework
+Copyright © 2006 Mikko Rasa, Mikkosoft Productions
+Distributed under the LGPL
+*/
+#ifndef MSP_FRAMEWORK_TYPES_H_
+#define MSP_FRAMEWORK_TYPES_H_
+
+#ifdef WIN32
+#include <windows.h>
+#else
+#include <pthread.h>
+#endif
+
+namespace Msp {
+
+#ifdef WIN32
+typedef HANDLE ThreadHandle;
+typedef HANDLE MutexHandle;
+#else
+typedef pthread_t ThreadHandle;
+typedef pthread_mutex_t MutexHandle;
+#endif
+
+} // namespace Msp
+
+#endif
+++ /dev/null
-/*
-This file is part of libmspframework
-Copyright © 2006 Mikko Rasa, Mikkosoft Productions
-Distributed under the LGPL
-*/
-#ifndef MSP_FRAMEWORK_WIN32SIGNUM_H_
-#define MSP_FRAMEWORK_WIN32SIGNUM_H_
-
-/* Fake signal functions. */
-#ifndef SIG_ERR
-#define SIG_ERR ((__sighandler_t) -1) /* Error return. */
-#endif
-#ifndef SIG_DFL
-#define SIG_DFL ((__sighandler_t) 0) /* Default action. */
-#endif
-#ifndef SIG_IGN
-#define SIG_IGN ((__sighandler_t) 1) /* Ignore signal. */
-#endif
-
-#if defined __USE_UNIX98 && !defined SIG_HOLD
-# define SIG_HOLD ((__sighandler_t) 2) /* Add signal to hold mask. */
-#endif
-
-/* Signals. */
-#define SIGHUP 1 /* Hangup (POSIX). */
-#define SIGINT 2 /* Interrupt (ANSI). */
-#define SIGQUIT 3 /* Quit (POSIX). */
-#define SIGILL 4 /* Illegal instruction (ANSI). */
-#define SIGTRAP 5 /* Trace trap (POSIX). */
-#ifndef SIGABRT
-#define SIGABRT 6 /* Abort (ANSI). */
-#endif
-#define SIGIOT 6 /* IOT trap (4.2 BSD). */
-#define SIGBUS 7 /* BUS error (4.2 BSD). */
-#define SIGFPE 8 /* Floating-point exception (ANSI). */
-#define SIGKILL 9 /* Kill, unblockable (POSIX). */
-#define SIGUSR1 10 /* User-defined signal 1 (POSIX). */
-#define SIGSEGV 11 /* Segmentation violation (ANSI). */
-#define SIGUSR2 12 /* User-defined signal 2 (POSIX). */
-#define SIGPIPE 13 /* Broken pipe (POSIX). */
-#define SIGALRM 14 /* Alarm clock (POSIX). */
-#define SIGTERM 15 /* Termination (ANSI). */
-#define SIGSTKFLT 16 /* Stack fault. */
-#define SIGCLD SIGCHLD /* Same as SIGCHLD (System V). */
-#define SIGCHLD 17 /* Child status has changed (POSIX). */
-#define SIGCONT 18 /* Continue (POSIX). */
-#define SIGSTOP 19 /* Stop, unblockable (POSIX). */
-#define SIGTSTP 20 /* Keyboard stop (POSIX). */
-#define SIGTTIN 21 /* Background read from tty (POSIX). */
-#define SIGTTOU 22 /* Background write to tty (POSIX). */
-#define SIGURG 23 /* Urgent condition on socket (4.2 BSD). */
-#define SIGXCPU 24 /* CPU limit exceeded (4.2 BSD). */
-#define SIGXFSZ 25 /* File size limit exceeded (4.2 BSD). */
-#define SIGVTALRM 26 /* Virtual alarm clock (4.2 BSD). */
-#define SIGPROF 27 /* Profiling alarm clock (4.2 BSD). */
-#define SIGWINCH 28 /* Window size change (4.3 BSD, Sun). */
-#define SIGPOLL SIGIO /* Pollable event occurred (System V). */
-#define SIGIO 29 /* I/O now possible (4.2 BSD). */
-#define SIGPWR 30 /* Power failure restart (System V). */
-#define SIGSYS 31 /* Bad system call. */
-#define SIGUNUSED 31
-
-#define _NSIG 65 /* Biggest signal number + 1
- (including real-time signals). */
-
-#define SIGRTMIN (__libc_current_sigrtmin ())
-#define SIGRTMAX (__libc_current_sigrtmax ())
-
-/* These are the hard limits of the kernel. These values should not be
- used directly at user level. */
-#define __SIGRTMIN 32
-#define __SIGRTMAX (_NSIG - 1)
-
-#endif