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 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198
|
/*
FALCON - Falcon advanced simple text evaluator.
FILE: systhread_win.cpp
System dependent MT provider - MS-Windows specific.
-------------------------------------------------------------------
Author: Giancarlo Niccolai
Begin: Wed, 09 Apr 2008 21:32:31 +0200
-------------------------------------------------------------------
(C) Copyright 2008: the FALCON developers (see list in AUTHORS file)
See LICENSE file for licensing details.
*/
/** \file
System dependent MT provider - MS-Windows specific.
*/
#include "systhread_win.h"
#include <falcon/memory.h>
#include <falcon/vm_sys.h>
#include <falcon/vm_sys_win.h>
#include "waitable.h"
#include "systhread.h"
#include "threading_mod.h"
#include <process.h>
static DWORD runningThreadKey = 0;
namespace Falcon {
namespace Ext {
//======================================================
// Waitable
//
void WaitableProvider::init( Waitable *wo )
{
wo->m_sysData = CreateEvent( NULL, TRUE, FALSE, NULL );
}
void WaitableProvider::destroy( Waitable *wo )
{
CloseHandle( ( HANDLE) wo->m_sysData );
}
void WaitableProvider::signal( Waitable *wo )
{
SetEvent( (HANDLE) wo->m_sysData );
}
void WaitableProvider::broadcast( Waitable *wo )
{
PulseEvent( (HANDLE) wo->m_sysData );
}
//======================================================
// Thread
//
WIN_THI_DATA::WIN_THI_DATA()
{
hth = INVALID_HANDLE_VALUE;
thID = 0;
lastError = 0;
}
WIN_THI_DATA::~WIN_THI_DATA()
{
if( hth != INVALID_HANDLE_VALUE )
CloseHandle( hth );
}
void WaitableProvider::interruptWaits( ThreadImpl *runner )
{
// dummy; under windows interrupting the VM is enough
}
int WaitableProvider::waitForObjects( const ThreadImpl *runner, int32 count, Waitable **objects, int64 time )
{
WIN_THI_DATA *data = (WIN_THI_DATA *) runner->sysData();
const ::Falcon::Sys::SystemData &sd = runner->vm().systemData();
// first, let's see if we have some data ready
// in case of no wait, just check for availability
for ( int32 i = 0; i < count; i++ )
{
// try-acquire semantic.
if ( objects[i]->acquire() )
{
// eventually clear signalation on this object
WaitForSingleObject( (HANDLE) objects[i]->m_sysData, 0 );
return i;
}
}
// noway.
if ( time == 0 )
return -1;
HANDLE waited[ MAX_WAITER_OBJECTS ];
for ( int wid = 0; wid < count && wid < MAX_WAITER_OBJECTS; wid ++ )
waited[wid] = (HANDLE) objects[wid]->m_sysData;
int cancHandle;
Sys::VM_SYS_DATA* vmsd = sd.m_sysData;
if ( vmsd->evtInterrupt != INVALID_HANDLE_VALUE )
{
waited[count] = vmsd->evtInterrupt;
cancHandle = 1;
}
else
cancHandle = 0;
// TODO: Add cancellation event
DWORD now;
DWORD targetTime;
if( time < 0 )
{
now = 0;
targetTime = INFINITE;
}
else
{
now = ::GetTickCount();
targetTime = now + (DWORD)(time/1000);
}
// now wait till we can acquire something.
int acquired = -1;
while( true )
{
DWORD res = WaitForMultipleObjects( count+cancHandle, waited, FALSE, targetTime - now );
if ( res == WAIT_TIMEOUT )
{
// nothing to do...
return -1;
}
else if ( res == WAIT_OBJECT_0 + count )
{
// Cancelled
return -2;
}
// try to acquire the signaled item.
acquired = res - WAIT_OBJECT_0;
if ( acquired < 0 || acquired >= count || ! objects[acquired]->acquire() )
{
// try again. If we have a target time, update wait
if ( time > 0 )
{
now = ::GetTickCount();
if ( now >= targetTime )
{
// we timed out
return -1;
}
// otherwise, continue
}
}
else {
// we acquired the object
// Reset the event; just to prevent other wakeups, even if we know that some went.
ResetEvent( (HANDLE) objects[acquired]->m_sysData );
break; // so we can return outside the loop
}
}
return acquired;
}
void* createSysData() {
return new WIN_THI_DATA;
}
void disposeSysData( void *data )
{
if ( data != 0 )
{
WIN_THI_DATA* ptr = (WIN_THI_DATA*) data;
delete ptr;
}
}
}
}
/* end of systhread_win.cpp */
|