2
3
mirror of https://foundry.openuru.org/gitblit/r/CWE-ou-minkata.git synced 2025-07-13 18:17:49 -04:00

Fix line endings and tabs

This commit is contained in:
Branan Purvine-Riley
2011-04-11 16:27:55 -07:00
parent d4250e19b5
commit 908aaeb6f6
2738 changed files with 702562 additions and 702562 deletions

View File

@ -1,484 +1,484 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
/*****************************************************************************
*
* $/Plasma20/Sources/Plasma/NucleusLib/pnAsyncCoreExe/Private/Nt/pnAceNt.cpp
*
***/
#include "../../Pch.h"
#pragma hdrstop
#include "pnAceNtInt.h"
namespace Nt {
/****************************************************************************
*
* Private data
*
***/
// Use non-allocated arrays for worker threads since they're used so frequently.
const unsigned kMaxWorkerThreads = 32; // handles 8-processor computer w/hyperthreading
static bool s_running;
static HANDLE s_waitEvent;
static long s_ioThreadCount;
static HANDLE s_ioThreadHandles[kMaxWorkerThreads];
static HANDLE s_ioPort;
static unsigned s_pageSizeMask;
/****************************************************************************
*
* Waitable event handles
*
***/
//===========================================================================
CNtWaitHandle::CNtWaitHandle () {
m_refCount = 1;
m_event = CreateEvent(
(LPSECURITY_ATTRIBUTES) nil,
true, // manual reset
false, // initial state
(LPCTSTR) nil
);
}
//===========================================================================
CNtWaitHandle::~CNtWaitHandle () {
CloseHandle(m_event);
}
//===========================================================================
void CNtWaitHandle::IncRef () {
InterlockedIncrement(&m_refCount);
}
//===========================================================================
void CNtWaitHandle::DecRef () {
if (!InterlockedDecrement(&m_refCount))
DEL(this);
}
//===========================================================================
bool CNtWaitHandle::WaitForObject (unsigned timeMs) const {
return WAIT_TIMEOUT != WaitForSingleObject(m_event, timeMs);
}
//===========================================================================
void CNtWaitHandle::SignalObject () const {
SetEvent(m_event);
}
/****************************************************************************
*
* OPERATIONS
*
***/
//===========================================================================
static void INtOpDispatch (
NtObject * ntObj,
Operation * op,
dword bytes
) {
for (;;) {
switch (op->opType) {
case kOpConnAttempt:
INtSocketOpCompleteSocketConnect((NtOpConnAttempt *) op);
// operation not associated with ntObj so there is no next operation.
// operation has already been deleted by OpCompleteSocketConnect.
return;
case kOpQueuedSocketWrite:
INtSocketOpCompleteQueuedSocketWrite((NtSock *) ntObj, (NtOpSocketWrite *) op);
// operation converted into kOpSocketWrite so we cannot move
// to next operation until write operation completes
return;
case kOpSocketRead:
ASSERT(bytes != (dword) -1);
INtSocketOpCompleteSocketRead((NtSock *) ntObj, bytes);
return;
case kOpSocketWrite:
ASSERT(bytes != (dword) -1);
INtSocketOpCompleteSocketWrite((NtSock *) ntObj, (NtOpSocketWrite *) op);
break;
case kOpQueuedFileRead:
case kOpQueuedFileWrite:
INtFileOpCompleteQueuedReadWrite((NtFile *) ntObj, (NtOpFileReadWrite *) op);
// operation converted into kOpFileWrite so we cannot move
// to next operation until write operation completes
return;
case kOpFileRead:
case kOpFileWrite:
ASSERT(bytes != (dword) -1);
if (!INtFileOpCompleteReadWrite((NtFile *) ntObj, (NtOpFileReadWrite *) op, bytes))
return;
break;
case kOpFileFlush:
INtFileOpCompleteFileFlush((NtFile *) ntObj, (NtOpFileFlush *) op);
break;
case kOpSequence:
INtFileOpCompleteSequence((NtFile *) ntObj, (NtOpFileSequence *) op);
break;
DEFAULT_FATAL(opType);
}
// if this operation is not at the head of the list then it can't be completed
// because nextCompleteSequence would be prematurely incremented. Instead
// convert the operation to OP_NULL, which will get completed when it reaches
// the head of the list.
ntObj->critsect.Enter();
if (ntObj->opList.Prev(op)) {
// setting the completion flag must be done inside the critical section
// because it will be checked by sibling operations when they have the
// critical section.
op->pending = 0;
ntObj->critsect.Leave();
return;
}
// complete processing this event, and, since we're still inside the critical
// section, finish all completed operations since we don't have to leave the
// critical section to do so. This is a big win because a single operation
// that takes a long time to complete can backlog a long list of completed ops.
bool continueDispatch;
for (;;) {
// wake up any other threads waiting on this event
CNtWaitHandle * signalComplete = op->signalComplete;
op->signalComplete = nil;
// since this operation is at the head of the list we can complete it
if (op->asyncId && !++ntObj->nextCompleteSequence)
++ntObj->nextCompleteSequence;
Operation * next = ntObj->opList.Next(op);
ntObj->opList.Delete(op);
op = next;
// set event *after* operation is complete
if (signalComplete) {
signalComplete->SignalObject();
signalComplete->DecRef();
}
// if we just deleted the last operation then stop dispatching
if (!op) {
continueDispatch = false;
break;
}
// opTypes >= kOpSequence complete when they reach the head of the list
continueDispatch = op->opType >= kOpSequence;
if (op->pending)
break;
InterlockedDecrement(&ntObj->ioCount);
}
ntObj->critsect.Leave();
INtConnCompleteOperation(ntObj);
if (!continueDispatch)
break;
// certain operations which depend upon the value of bytes (reads & writes)
// can only be dispatched when they are completed normally. To ensure that
// we're not accidentally processing an operation that shouldn't be executed,
// set the bytes field to an invalid value.
bytes = (dword) -1;
}
}
//===========================================================================
static unsigned THREADCALL NtWorkerThreadProc (AsyncThread * thread) {
ThreadDenyBlock();
unsigned sleepMs = INFINITE;
while (s_running) {
// process I/O operations
{
dword bytes;
NtObject * ntObj;
Operation * op;
(void) GetQueuedCompletionStatus(
s_ioPort,
&bytes,
#ifdef _WIN64
(PULONG_PTR) &ntObj,
#else
(LPDWORD) &ntObj,
#endif
(LPOVERLAPPED *) &op,
sleepMs
);
if (op) {
// Queue for deadlock detection
#ifdef SERVER
void * check = CrashAddDeadlockCheck(thread->handle, L"pnAceNt.NtWorkerThread");
#endif
// Dispatch event to app
INtOpDispatch(ntObj, op, bytes);
// Unqueue from deadlock detection
#ifdef SERVER
CrashRemoveDeadlockCheck(check);
#endif
sleepMs = 0;
continue;
}
}
sleepMs = INFINITE;
continue;
}
return 0;
}
/****************************************************************************
*
* Module functions
*
***/
//===========================================================================
void INtConnPostOperation (NtObject * ntObj, Operation * op, unsigned bytes) {
PostQueuedCompletionStatus(
s_ioPort,
bytes,
#ifdef _WIN64
(ULONG_PTR) ntObj,
#else
(DWORD) ntObj,
#endif
&op->overlapped
);
}
//===========================================================================
AsyncId INtConnSequenceStart (NtObject * ntObj) {
unsigned result;
if (0 == (result = ++ntObj->nextStartSequence))
result = ++ntObj->nextStartSequence;
return (AsyncId) result;
}
//===========================================================================
bool INtConnInitialize (NtObject * ntObj) {
if (!CreateIoCompletionPort(ntObj->handle, s_ioPort, (DWORD) ntObj, 0)) {
LogMsg(kLogFatal, "CreateIoCompletionPort failed");
return false;
}
return true;
}
//===========================================================================
void INtConnCompleteOperation (NtObject * ntObj) {
// are we completing the last operation for this object?
if (InterlockedDecrement(&ntObj->ioCount))
return;
DWORD err = GetLastError();
switch (ntObj->ioType) {
case kNtFile:
INtFileDelete((NtFile *) ntObj);
break;
case kNtSocket:
INtSockDelete((NtSock *) ntObj);
break;
default:
LogMsg(kLogError, "NtConnCompleteOp %p %u", ntObj, ntObj->ioType);
break;
}
}
/*****************************************************************************
*
* Module exports
*
***/
//===========================================================================
void NtInitialize () {
// ensure initialization only occurs once
if (s_running)
return;
s_running = true;
// create a cleanup event
s_waitEvent = CreateEvent(
(LPSECURITY_ATTRIBUTES) 0,
true, // manual reset
false, // initial state off
(LPCTSTR) nil // name
);
if (!s_waitEvent)
ErrorFatal(__LINE__, __FILE__, "CreateEvent %#x", GetLastError());
// create IO completion port
if (0 == (s_ioPort = CreateIoCompletionPort(INVALID_HANDLE_VALUE, 0, 0, 0)))
ErrorFatal(__LINE__, __FILE__, "CreateIoCompletionPort %#x", GetLastError());
// calculate number of IO worker threads to create
if (!s_pageSizeMask) {
SYSTEM_INFO si;
GetSystemInfo(&si);
s_pageSizeMask = si.dwPageSize - 1;
// Set worker thread count
s_ioThreadCount = si.dwNumberOfProcessors * 2;
if (s_ioThreadCount > kMaxWorkerThreads) {
s_ioThreadCount = kMaxWorkerThreads;
LogMsg(kLogError, "kMaxWorkerThreads too small!");
}
}
// create IO worker threads
for (long thread = 0; thread < s_ioThreadCount; thread++) {
s_ioThreadHandles[thread] = (HANDLE) AsyncThreadCreate(
NtWorkerThreadProc,
(void *) thread,
L"NtWorkerThread"
);
}
INtFileInitialize();
INtSocketInitialize();
}
//===========================================================================
// DANGER: calling this function will slam closed any files which are still open.
// MOST PROGRAMS DO NOT NEED TO CALL THIS FUNCTION. In general, the best way to
// shut down the program is to simply let the atexit() handler take care of it.
void NtDestroy (unsigned exitThreadWaitMs) {
// cleanup modules that post completion notifications as part of their shutdown
INtFileStartCleanup();
INtSocketStartCleanup(exitThreadWaitMs);
// cleanup worker threads
s_running = false;
if (s_ioPort) {
// Post a completion notification to worker threads to wake them up
long thread;
for (thread = 0; thread < s_ioThreadCount; thread++)
PostQueuedCompletionStatus(s_ioPort, 0, 0, 0);
// Close each thread
for (thread = 0; thread < s_ioThreadCount; thread++) {
if (s_ioThreadHandles[thread]) {
WaitForSingleObject(s_ioThreadHandles[thread], exitThreadWaitMs);
CloseHandle(s_ioThreadHandles[thread]);
s_ioThreadHandles[thread] = nil;
}
}
// Cleanup port
CloseHandle(s_ioPort);
s_ioPort = 0;
}
if (s_waitEvent) {
CloseHandle(s_waitEvent);
s_waitEvent = 0;
}
INtFileDestroy();
INtSocketDestroy();
}
//===========================================================================
void NtSignalShutdown () {
SetEvent(s_waitEvent);
}
//===========================================================================
void NtWaitForShutdown () {
if (s_waitEvent)
WaitForSingleObject(s_waitEvent, INFINITE);
}
} using namespace Nt;
/****************************************************************************
*
* Public exports
*
***/
//===========================================================================
void NtGetApi (AsyncApi * api) {
api->initialize = NtInitialize;
api->destroy = NtDestroy;
api->signalShutdown = NtSignalShutdown;
api->waitForShutdown = NtWaitForShutdown;
api->sleep = NtSleep;
api->fileOpen = NtFileOpen;
api->fileClose = NtFileClose;
api->fileRead = NtFileRead;
api->fileWrite = NtFileWrite;
api->fileFlushBuffers = NtFileFlushBuffers;
api->fileSetLastWriteTime = NtFileSetLastWriteTime;
api->fileGetLastWriteTime = NtFileGetLastWriteTime;
api->fileCreateSequence = NtFileCreateSequence;
api->fileSeek = NtFileSeek;
api->socketConnect = NtSocketConnect;
api->socketConnectCancel = NtSocketConnectCancel;
api->socketDisconnect = NtSocketDisconnect;
api->socketDelete = NtSocketDelete;
api->socketSend = NtSocketSend;
api->socketWrite = NtSocketWrite;
api->socketSetNotifyProc = NtSocketSetNotifyProc;
api->socketSetBacklogAlloc = NtSocketSetBacklogAlloc;
api->socketStartListening = NtSocketStartListening;
api->socketStopListening = NtSocketStopListening;
api->socketEnableNagling = NtSocketEnableNagling;
}
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
/*****************************************************************************
*
* $/Plasma20/Sources/Plasma/NucleusLib/pnAsyncCoreExe/Private/Nt/pnAceNt.cpp
*
***/
#include "../../Pch.h"
#pragma hdrstop
#include "pnAceNtInt.h"
namespace Nt {
/****************************************************************************
*
* Private data
*
***/
// Use non-allocated arrays for worker threads since they're used so frequently.
const unsigned kMaxWorkerThreads = 32; // handles 8-processor computer w/hyperthreading
static bool s_running;
static HANDLE s_waitEvent;
static long s_ioThreadCount;
static HANDLE s_ioThreadHandles[kMaxWorkerThreads];
static HANDLE s_ioPort;
static unsigned s_pageSizeMask;
/****************************************************************************
*
* Waitable event handles
*
***/
//===========================================================================
CNtWaitHandle::CNtWaitHandle () {
m_refCount = 1;
m_event = CreateEvent(
(LPSECURITY_ATTRIBUTES) nil,
true, // manual reset
false, // initial state
(LPCTSTR) nil
);
}
//===========================================================================
CNtWaitHandle::~CNtWaitHandle () {
CloseHandle(m_event);
}
//===========================================================================
void CNtWaitHandle::IncRef () {
InterlockedIncrement(&m_refCount);
}
//===========================================================================
void CNtWaitHandle::DecRef () {
if (!InterlockedDecrement(&m_refCount))
DEL(this);
}
//===========================================================================
bool CNtWaitHandle::WaitForObject (unsigned timeMs) const {
return WAIT_TIMEOUT != WaitForSingleObject(m_event, timeMs);
}
//===========================================================================
void CNtWaitHandle::SignalObject () const {
SetEvent(m_event);
}
/****************************************************************************
*
* OPERATIONS
*
***/
//===========================================================================
static void INtOpDispatch (
NtObject * ntObj,
Operation * op,
dword bytes
) {
for (;;) {
switch (op->opType) {
case kOpConnAttempt:
INtSocketOpCompleteSocketConnect((NtOpConnAttempt *) op);
// operation not associated with ntObj so there is no next operation.
// operation has already been deleted by OpCompleteSocketConnect.
return;
case kOpQueuedSocketWrite:
INtSocketOpCompleteQueuedSocketWrite((NtSock *) ntObj, (NtOpSocketWrite *) op);
// operation converted into kOpSocketWrite so we cannot move
// to next operation until write operation completes
return;
case kOpSocketRead:
ASSERT(bytes != (dword) -1);
INtSocketOpCompleteSocketRead((NtSock *) ntObj, bytes);
return;
case kOpSocketWrite:
ASSERT(bytes != (dword) -1);
INtSocketOpCompleteSocketWrite((NtSock *) ntObj, (NtOpSocketWrite *) op);
break;
case kOpQueuedFileRead:
case kOpQueuedFileWrite:
INtFileOpCompleteQueuedReadWrite((NtFile *) ntObj, (NtOpFileReadWrite *) op);
// operation converted into kOpFileWrite so we cannot move
// to next operation until write operation completes
return;
case kOpFileRead:
case kOpFileWrite:
ASSERT(bytes != (dword) -1);
if (!INtFileOpCompleteReadWrite((NtFile *) ntObj, (NtOpFileReadWrite *) op, bytes))
return;
break;
case kOpFileFlush:
INtFileOpCompleteFileFlush((NtFile *) ntObj, (NtOpFileFlush *) op);
break;
case kOpSequence:
INtFileOpCompleteSequence((NtFile *) ntObj, (NtOpFileSequence *) op);
break;
DEFAULT_FATAL(opType);
}
// if this operation is not at the head of the list then it can't be completed
// because nextCompleteSequence would be prematurely incremented. Instead
// convert the operation to OP_NULL, which will get completed when it reaches
// the head of the list.
ntObj->critsect.Enter();
if (ntObj->opList.Prev(op)) {
// setting the completion flag must be done inside the critical section
// because it will be checked by sibling operations when they have the
// critical section.
op->pending = 0;
ntObj->critsect.Leave();
return;
}
// complete processing this event, and, since we're still inside the critical
// section, finish all completed operations since we don't have to leave the
// critical section to do so. This is a big win because a single operation
// that takes a long time to complete can backlog a long list of completed ops.
bool continueDispatch;
for (;;) {
// wake up any other threads waiting on this event
CNtWaitHandle * signalComplete = op->signalComplete;
op->signalComplete = nil;
// since this operation is at the head of the list we can complete it
if (op->asyncId && !++ntObj->nextCompleteSequence)
++ntObj->nextCompleteSequence;
Operation * next = ntObj->opList.Next(op);
ntObj->opList.Delete(op);
op = next;
// set event *after* operation is complete
if (signalComplete) {
signalComplete->SignalObject();
signalComplete->DecRef();
}
// if we just deleted the last operation then stop dispatching
if (!op) {
continueDispatch = false;
break;
}
// opTypes >= kOpSequence complete when they reach the head of the list
continueDispatch = op->opType >= kOpSequence;
if (op->pending)
break;
InterlockedDecrement(&ntObj->ioCount);
}
ntObj->critsect.Leave();
INtConnCompleteOperation(ntObj);
if (!continueDispatch)
break;
// certain operations which depend upon the value of bytes (reads & writes)
// can only be dispatched when they are completed normally. To ensure that
// we're not accidentally processing an operation that shouldn't be executed,
// set the bytes field to an invalid value.
bytes = (dword) -1;
}
}
//===========================================================================
static unsigned THREADCALL NtWorkerThreadProc (AsyncThread * thread) {
ThreadDenyBlock();
unsigned sleepMs = INFINITE;
while (s_running) {
// process I/O operations
{
dword bytes;
NtObject * ntObj;
Operation * op;
(void) GetQueuedCompletionStatus(
s_ioPort,
&bytes,
#ifdef _WIN64
(PULONG_PTR) &ntObj,
#else
(LPDWORD) &ntObj,
#endif
(LPOVERLAPPED *) &op,
sleepMs
);
if (op) {
// Queue for deadlock detection
#ifdef SERVER
void * check = CrashAddDeadlockCheck(thread->handle, L"pnAceNt.NtWorkerThread");
#endif
// Dispatch event to app
INtOpDispatch(ntObj, op, bytes);
// Unqueue from deadlock detection
#ifdef SERVER
CrashRemoveDeadlockCheck(check);
#endif
sleepMs = 0;
continue;
}
}
sleepMs = INFINITE;
continue;
}
return 0;
}
/****************************************************************************
*
* Module functions
*
***/
//===========================================================================
void INtConnPostOperation (NtObject * ntObj, Operation * op, unsigned bytes) {
PostQueuedCompletionStatus(
s_ioPort,
bytes,
#ifdef _WIN64
(ULONG_PTR) ntObj,
#else
(DWORD) ntObj,
#endif
&op->overlapped
);
}
//===========================================================================
AsyncId INtConnSequenceStart (NtObject * ntObj) {
unsigned result;
if (0 == (result = ++ntObj->nextStartSequence))
result = ++ntObj->nextStartSequence;
return (AsyncId) result;
}
//===========================================================================
bool INtConnInitialize (NtObject * ntObj) {
if (!CreateIoCompletionPort(ntObj->handle, s_ioPort, (DWORD) ntObj, 0)) {
LogMsg(kLogFatal, "CreateIoCompletionPort failed");
return false;
}
return true;
}
//===========================================================================
void INtConnCompleteOperation (NtObject * ntObj) {
// are we completing the last operation for this object?
if (InterlockedDecrement(&ntObj->ioCount))
return;
DWORD err = GetLastError();
switch (ntObj->ioType) {
case kNtFile:
INtFileDelete((NtFile *) ntObj);
break;
case kNtSocket:
INtSockDelete((NtSock *) ntObj);
break;
default:
LogMsg(kLogError, "NtConnCompleteOp %p %u", ntObj, ntObj->ioType);
break;
}
}
/*****************************************************************************
*
* Module exports
*
***/
//===========================================================================
void NtInitialize () {
// ensure initialization only occurs once
if (s_running)
return;
s_running = true;
// create a cleanup event
s_waitEvent = CreateEvent(
(LPSECURITY_ATTRIBUTES) 0,
true, // manual reset
false, // initial state off
(LPCTSTR) nil // name
);
if (!s_waitEvent)
ErrorFatal(__LINE__, __FILE__, "CreateEvent %#x", GetLastError());
// create IO completion port
if (0 == (s_ioPort = CreateIoCompletionPort(INVALID_HANDLE_VALUE, 0, 0, 0)))
ErrorFatal(__LINE__, __FILE__, "CreateIoCompletionPort %#x", GetLastError());
// calculate number of IO worker threads to create
if (!s_pageSizeMask) {
SYSTEM_INFO si;
GetSystemInfo(&si);
s_pageSizeMask = si.dwPageSize - 1;
// Set worker thread count
s_ioThreadCount = si.dwNumberOfProcessors * 2;
if (s_ioThreadCount > kMaxWorkerThreads) {
s_ioThreadCount = kMaxWorkerThreads;
LogMsg(kLogError, "kMaxWorkerThreads too small!");
}
}
// create IO worker threads
for (long thread = 0; thread < s_ioThreadCount; thread++) {
s_ioThreadHandles[thread] = (HANDLE) AsyncThreadCreate(
NtWorkerThreadProc,
(void *) thread,
L"NtWorkerThread"
);
}
INtFileInitialize();
INtSocketInitialize();
}
//===========================================================================
// DANGER: calling this function will slam closed any files which are still open.
// MOST PROGRAMS DO NOT NEED TO CALL THIS FUNCTION. In general, the best way to
// shut down the program is to simply let the atexit() handler take care of it.
void NtDestroy (unsigned exitThreadWaitMs) {
// cleanup modules that post completion notifications as part of their shutdown
INtFileStartCleanup();
INtSocketStartCleanup(exitThreadWaitMs);
// cleanup worker threads
s_running = false;
if (s_ioPort) {
// Post a completion notification to worker threads to wake them up
long thread;
for (thread = 0; thread < s_ioThreadCount; thread++)
PostQueuedCompletionStatus(s_ioPort, 0, 0, 0);
// Close each thread
for (thread = 0; thread < s_ioThreadCount; thread++) {
if (s_ioThreadHandles[thread]) {
WaitForSingleObject(s_ioThreadHandles[thread], exitThreadWaitMs);
CloseHandle(s_ioThreadHandles[thread]);
s_ioThreadHandles[thread] = nil;
}
}
// Cleanup port
CloseHandle(s_ioPort);
s_ioPort = 0;
}
if (s_waitEvent) {
CloseHandle(s_waitEvent);
s_waitEvent = 0;
}
INtFileDestroy();
INtSocketDestroy();
}
//===========================================================================
void NtSignalShutdown () {
SetEvent(s_waitEvent);
}
//===========================================================================
void NtWaitForShutdown () {
if (s_waitEvent)
WaitForSingleObject(s_waitEvent, INFINITE);
}
} using namespace Nt;
/****************************************************************************
*
* Public exports
*
***/
//===========================================================================
void NtGetApi (AsyncApi * api) {
api->initialize = NtInitialize;
api->destroy = NtDestroy;
api->signalShutdown = NtSignalShutdown;
api->waitForShutdown = NtWaitForShutdown;
api->sleep = NtSleep;
api->fileOpen = NtFileOpen;
api->fileClose = NtFileClose;
api->fileRead = NtFileRead;
api->fileWrite = NtFileWrite;
api->fileFlushBuffers = NtFileFlushBuffers;
api->fileSetLastWriteTime = NtFileSetLastWriteTime;
api->fileGetLastWriteTime = NtFileGetLastWriteTime;
api->fileCreateSequence = NtFileCreateSequence;
api->fileSeek = NtFileSeek;
api->socketConnect = NtSocketConnect;
api->socketConnectCancel = NtSocketConnectCancel;
api->socketDisconnect = NtSocketDisconnect;
api->socketDelete = NtSocketDelete;
api->socketSend = NtSocketSend;
api->socketWrite = NtSocketWrite;
api->socketSetNotifyProc = NtSocketSetNotifyProc;
api->socketSetBacklogAlloc = NtSocketSetBacklogAlloc;
api->socketStartListening = NtSocketStartListening;
api->socketStopListening = NtSocketStopListening;
api->socketEnableNagling = NtSocketEnableNagling;
}

View File

@ -1,48 +1,48 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
/*****************************************************************************
*
* $/Plasma20/Sources/Plasma/NucleusLib/pnAsyncCoreExe/Private/Nt/pnAceNt.h
*
***/
#ifdef PLASMA20_SOURCES_PLASMA_NUCLEUSLIB_PNASYNCCOREEXE_PRIVATE_NT_PNACENT_H
#error "Header $/Plasma20/Sources/Plasma/NucleusLib/pnAsyncCoreExe/Private/Nt/pnAceNt.h included more than once"
#endif
#define PLASMA20_SOURCES_PLASMA_NUCLEUSLIB_PNASYNCCOREEXE_PRIVATE_NT_PNACENT_H
#ifdef HS_BUILD_FOR_WIN32
/****************************************************************************
*
* Nt API functions
*
***/
void NtGetApi (AsyncApi * api);
#endif // HS_BUILD_FOR_WIN32
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
/*****************************************************************************
*
* $/Plasma20/Sources/Plasma/NucleusLib/pnAsyncCoreExe/Private/Nt/pnAceNt.h
*
***/
#ifdef PLASMA20_SOURCES_PLASMA_NUCLEUSLIB_PNASYNCCOREEXE_PRIVATE_NT_PNACENT_H
#error "Header $/Plasma20/Sources/Plasma/NucleusLib/pnAsyncCoreExe/Private/Nt/pnAceNt.h included more than once"
#endif
#define PLASMA20_SOURCES_PLASMA_NUCLEUSLIB_PNASYNCCOREEXE_PRIVATE_NT_PNACENT_H
#ifdef HS_BUILD_FOR_WIN32
/****************************************************************************
*
* Nt API functions
*
***/
void NtGetApi (AsyncApi * api);
#endif // HS_BUILD_FOR_WIN32

View File

@ -1,320 +1,320 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
/*****************************************************************************
*
* $/Plasma20/Sources/Plasma/NucleusLib/pnAsyncCoreExe/Private/Nt/pnAceNtInt.h
*
***/
#ifdef PLASMA20_SOURCES_PLASMA_NUCLEUSLIB_PNASYNCCOREEXE_PRIVATE_NT_PNACENTINT_H
#error "Header $/Plasma20/Sources/Plasma/NucleusLib/pnAsyncCoreExe/Private/Nt/pnAceNtInt.h included more than once"
#endif
#define PLASMA20_SOURCES_PLASMA_NUCLEUSLIB_PNASYNCCOREEXE_PRIVATE_NT_PNACENTINT_H
namespace Nt {
/****************************************************************************
*
* Type definitions
*
***/
enum EIoType {
kNtFile,
kNtSocket,
kIoTypes
};
enum EOpType {
// Completed by GetQueuedCompletionStatus
kOpConnAttempt,
kOpSocketRead,
kOpSocketWrite,
kOpFileRead,
kOpFileWrite,
// opType >= kOpSequence complete when they reach the head of the list
kOpSequence,
kOpFileFlush,
kOpQueuedFileRead,
kOpQueuedFileWrite,
kOpQueuedSocketWrite,
kNumOpTypes
};
class CNtCritSect : public CCritSect {
public:
BOOL TryEnter () { return TryEnterCriticalSection(&m_handle); }
};
class CNtWaitHandle {
long m_refCount;
HANDLE m_event;
public:
CNtWaitHandle ();
~CNtWaitHandle ();
void IncRef ();
void DecRef ();
bool WaitForObject (unsigned timeMs) const;
void SignalObject () const;
};
struct Operation {
OVERLAPPED overlapped;
EOpType opType;
AsyncId asyncId;
bool notify;
unsigned pending;
CNtWaitHandle * signalComplete;
LINK(Operation) link;
#ifdef HS_DEBUGGING
~Operation () {
ASSERT(!signalComplete);
}
#endif
};
struct NtObject {
CNtCritSect critsect;
EIoType ioType;
HANDLE handle;
void * userState;
LISTDECL(Operation, link) opList;
long nextCompleteSequence;
long nextStartSequence;
long ioCount;
bool closed;
};
/****************************************************************************
*
* Nt.cpp internal functions
*
***/
void INtWakeupMainIoThreads ();
void INtConnPostOperation (NtObject * ntObj, Operation * op, unsigned bytes);
AsyncId INtConnSequenceStart (NtObject * ntObj);
bool INtConnInitialize (NtObject * ntObj);
void INtConnCompleteOperation (NtObject * ntObj);
/*****************************************************************************
*
* NtFile.cpp internal functions
*
***/
struct NtFile;
struct NtOpFileFlush;
struct NtOpFileReadWrite;
struct NtOpFileSequence;
void INtFileInitialize ();
void INtFileStartCleanup ();
void INtFileDestroy ();
void INtFileDelete (
NtFile * file
);
bool INtFileOpCompleteReadWrite (
NtFile * ioConn,
NtOpFileReadWrite * op,
unsigned bytes
);
void INtFileOpCompleteQueuedReadWrite (
NtFile * ioConn,
NtOpFileReadWrite * op
);
void INtFileOpCompleteFileFlush (
NtFile * ioConn,
NtOpFileFlush * op
);
void INtFileOpCompleteSequence (
NtFile * ioConn,
NtOpFileSequence * op
);
void INtFileStartCleanup ();
/*****************************************************************************
*
* NtSocket.cpp internal functions
*
***/
struct NtSock;
struct NtOpConnAttempt;
struct NtOpSocketWrite;
void INtSocketInitialize ();
void INtSocketStartCleanup (unsigned exitThreadWaitMs);
void INtSocketDestroy ();
void INtSockDelete (
NtSock * sock
);
void INtSocketOpCompleteSocketConnect (
NtOpConnAttempt * op
);
void INtSocketOpCompleteSocketRead (
NtSock * sock,
unsigned bytes
);
void INtSocketOpCompleteSocketWrite (
NtSock * sock,
NtOpSocketWrite * op
);
bool INtSocketOpCompleteQueuedSocketWrite (
NtSock * sock,
NtOpSocketWrite * op
);
/*****************************************************************************
*
* NT Async API functions
*
***/
void NtInitialize ();
void NtDestroy (unsigned exitThreadWaitMs);
void NtSignalShutdown ();
void NtWaitForShutdown ();
void NtSleep (unsigned sleepMs);
AsyncFile NtFileOpen (
const wchar fullPath[],
FAsyncNotifyFileProc notifyProc,
EFileError * error,
unsigned desiredAccess,
unsigned openMode,
unsigned shareModeFlags,
void * userState,
qword * fileSize,
qword * fileLastWriteTime
);
void NtFileClose (
AsyncFile file,
qword truncateSize
);
void NtFileSetLastWriteTime (
AsyncFile file,
qword lastWriteTime
);
qword NtFileGetLastWriteTime (
const wchar fileName[]
);
AsyncId NtFileFlushBuffers (
AsyncFile file,
qword truncateSize,
bool notify,
void * param
);
AsyncId NtFileRead (
AsyncFile file,
qword offset,
void * buffer,
unsigned bytes,
unsigned flags,
void * param
);
AsyncId NtFileWrite (
AsyncFile file,
qword offset,
const void *buffer,
unsigned bytes,
unsigned flags,
void * param
);
AsyncId NtFileCreateSequence (
AsyncFile file,
bool notify,
void * param
);
bool NtFileSeek (
AsyncFile file,
qword distance,
EFileSeekFrom from
);
void NtSocketConnect (
AsyncCancelId * cancelId,
const NetAddress & netAddr,
FAsyncNotifySocketProc notifyProc,
void * param,
const void * sendData,
unsigned sendBytes,
unsigned connectMs,
unsigned localPort
);
void NtSocketConnectCancel (
FAsyncNotifySocketProc notifyProc,
AsyncCancelId cancelId
);
void NtSocketDisconnect (
AsyncSocket sock,
bool hardClose
);
void NtSocketDelete (AsyncSocket sock);
bool NtSocketSend (
AsyncSocket sock,
const void * data,
unsigned bytes
);
bool NtSocketWrite (
AsyncSocket sock,
const void * buffer,
unsigned bytes,
void * param
);
void NtSocketSetNotifyProc (
AsyncSocket sock,
FAsyncNotifySocketProc notifyProc
);
void NtSocketSetBacklogAlloc (
AsyncSocket sock,
unsigned bufferSize
);
unsigned NtSocketStartListening (
const NetAddress & listenAddr,
FAsyncNotifySocketProc notifyProc
);
void NtSocketStopListening (
const NetAddress & listenAddr,
FAsyncNotifySocketProc notifyProc
);
void NtSocketEnableNagling (
AsyncSocket conn,
bool enable
);
} // namespace Nt
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
/*****************************************************************************
*
* $/Plasma20/Sources/Plasma/NucleusLib/pnAsyncCoreExe/Private/Nt/pnAceNtInt.h
*
***/
#ifdef PLASMA20_SOURCES_PLASMA_NUCLEUSLIB_PNASYNCCOREEXE_PRIVATE_NT_PNACENTINT_H
#error "Header $/Plasma20/Sources/Plasma/NucleusLib/pnAsyncCoreExe/Private/Nt/pnAceNtInt.h included more than once"
#endif
#define PLASMA20_SOURCES_PLASMA_NUCLEUSLIB_PNASYNCCOREEXE_PRIVATE_NT_PNACENTINT_H
namespace Nt {
/****************************************************************************
*
* Type definitions
*
***/
enum EIoType {
kNtFile,
kNtSocket,
kIoTypes
};
enum EOpType {
// Completed by GetQueuedCompletionStatus
kOpConnAttempt,
kOpSocketRead,
kOpSocketWrite,
kOpFileRead,
kOpFileWrite,
// opType >= kOpSequence complete when they reach the head of the list
kOpSequence,
kOpFileFlush,
kOpQueuedFileRead,
kOpQueuedFileWrite,
kOpQueuedSocketWrite,
kNumOpTypes
};
class CNtCritSect : public CCritSect {
public:
BOOL TryEnter () { return TryEnterCriticalSection(&m_handle); }
};
class CNtWaitHandle {
long m_refCount;
HANDLE m_event;
public:
CNtWaitHandle ();
~CNtWaitHandle ();
void IncRef ();
void DecRef ();
bool WaitForObject (unsigned timeMs) const;
void SignalObject () const;
};
struct Operation {
OVERLAPPED overlapped;
EOpType opType;
AsyncId asyncId;
bool notify;
unsigned pending;
CNtWaitHandle * signalComplete;
LINK(Operation) link;
#ifdef HS_DEBUGGING
~Operation () {
ASSERT(!signalComplete);
}
#endif
};
struct NtObject {
CNtCritSect critsect;
EIoType ioType;
HANDLE handle;
void * userState;
LISTDECL(Operation, link) opList;
long nextCompleteSequence;
long nextStartSequence;
long ioCount;
bool closed;
};
/****************************************************************************
*
* Nt.cpp internal functions
*
***/
void INtWakeupMainIoThreads ();
void INtConnPostOperation (NtObject * ntObj, Operation * op, unsigned bytes);
AsyncId INtConnSequenceStart (NtObject * ntObj);
bool INtConnInitialize (NtObject * ntObj);
void INtConnCompleteOperation (NtObject * ntObj);
/*****************************************************************************
*
* NtFile.cpp internal functions
*
***/
struct NtFile;
struct NtOpFileFlush;
struct NtOpFileReadWrite;
struct NtOpFileSequence;
void INtFileInitialize ();
void INtFileStartCleanup ();
void INtFileDestroy ();
void INtFileDelete (
NtFile * file
);
bool INtFileOpCompleteReadWrite (
NtFile * ioConn,
NtOpFileReadWrite * op,
unsigned bytes
);
void INtFileOpCompleteQueuedReadWrite (
NtFile * ioConn,
NtOpFileReadWrite * op
);
void INtFileOpCompleteFileFlush (
NtFile * ioConn,
NtOpFileFlush * op
);
void INtFileOpCompleteSequence (
NtFile * ioConn,
NtOpFileSequence * op
);
void INtFileStartCleanup ();
/*****************************************************************************
*
* NtSocket.cpp internal functions
*
***/
struct NtSock;
struct NtOpConnAttempt;
struct NtOpSocketWrite;
void INtSocketInitialize ();
void INtSocketStartCleanup (unsigned exitThreadWaitMs);
void INtSocketDestroy ();
void INtSockDelete (
NtSock * sock
);
void INtSocketOpCompleteSocketConnect (
NtOpConnAttempt * op
);
void INtSocketOpCompleteSocketRead (
NtSock * sock,
unsigned bytes
);
void INtSocketOpCompleteSocketWrite (
NtSock * sock,
NtOpSocketWrite * op
);
bool INtSocketOpCompleteQueuedSocketWrite (
NtSock * sock,
NtOpSocketWrite * op
);
/*****************************************************************************
*
* NT Async API functions
*
***/
void NtInitialize ();
void NtDestroy (unsigned exitThreadWaitMs);
void NtSignalShutdown ();
void NtWaitForShutdown ();
void NtSleep (unsigned sleepMs);
AsyncFile NtFileOpen (
const wchar fullPath[],
FAsyncNotifyFileProc notifyProc,
EFileError * error,
unsigned desiredAccess,
unsigned openMode,
unsigned shareModeFlags,
void * userState,
qword * fileSize,
qword * fileLastWriteTime
);
void NtFileClose (
AsyncFile file,
qword truncateSize
);
void NtFileSetLastWriteTime (
AsyncFile file,
qword lastWriteTime
);
qword NtFileGetLastWriteTime (
const wchar fileName[]
);
AsyncId NtFileFlushBuffers (
AsyncFile file,
qword truncateSize,
bool notify,
void * param
);
AsyncId NtFileRead (
AsyncFile file,
qword offset,
void * buffer,
unsigned bytes,
unsigned flags,
void * param
);
AsyncId NtFileWrite (
AsyncFile file,
qword offset,
const void *buffer,
unsigned bytes,
unsigned flags,
void * param
);
AsyncId NtFileCreateSequence (
AsyncFile file,
bool notify,
void * param
);
bool NtFileSeek (
AsyncFile file,
qword distance,
EFileSeekFrom from
);
void NtSocketConnect (
AsyncCancelId * cancelId,
const NetAddress & netAddr,
FAsyncNotifySocketProc notifyProc,
void * param,
const void * sendData,
unsigned sendBytes,
unsigned connectMs,
unsigned localPort
);
void NtSocketConnectCancel (
FAsyncNotifySocketProc notifyProc,
AsyncCancelId cancelId
);
void NtSocketDisconnect (
AsyncSocket sock,
bool hardClose
);
void NtSocketDelete (AsyncSocket sock);
bool NtSocketSend (
AsyncSocket sock,
const void * data,
unsigned bytes
);
bool NtSocketWrite (
AsyncSocket sock,
const void * buffer,
unsigned bytes,
void * param
);
void NtSocketSetNotifyProc (
AsyncSocket sock,
FAsyncNotifySocketProc notifyProc
);
void NtSocketSetBacklogAlloc (
AsyncSocket sock,
unsigned bufferSize
);
unsigned NtSocketStartListening (
const NetAddress & listenAddr,
FAsyncNotifySocketProc notifyProc
);
void NtSocketStopListening (
const NetAddress & listenAddr,
FAsyncNotifySocketProc notifyProc
);
void NtSocketEnableNagling (
AsyncSocket conn,
bool enable
);
} // namespace Nt

View File

@ -1,52 +1,52 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
/*****************************************************************************
*
* $/Plasma20/Sources/Plasma/NucleusLib/pnAsyncCoreExe/Private/Nt/pnAceNtThread.cpp
*
***/
#include "../../Pch.h"
#pragma hdrstop
#include "pnAceNtInt.h"
namespace Nt {
/*****************************************************************************
*
* Module exports
*
***/
//===========================================================================
void NtSleep (unsigned sleepMs) {
ThreadAssertCanBlock(__FILE__, __LINE__);
Sleep(sleepMs);
}
} using namespace Nt;
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
/*****************************************************************************
*
* $/Plasma20/Sources/Plasma/NucleusLib/pnAsyncCoreExe/Private/Nt/pnAceNtThread.cpp
*
***/
#include "../../Pch.h"
#pragma hdrstop
#include "pnAceNtInt.h"
namespace Nt {
/*****************************************************************************
*
* Module exports
*
***/
//===========================================================================
void NtSleep (unsigned sleepMs) {
ThreadAssertCanBlock(__FILE__, __LINE__);
Sleep(sleepMs);
}
} using namespace Nt;

View File

@ -1,48 +1,48 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
/*****************************************************************************
*
* $/Plasma20/Sources/Plasma/NucleusLib/pnAsyncCoreExe/Private/Unix/pnAceUx.h
*
***/
#ifdef PLASMA20_SOURCES_PLASMA_NUCLEUSLIB_PNASYNCCOREEXE_PRIVATE_UNIX_PNACEUX_H
#error "Header $/Plasma20/Sources/Plasma/NucleusLib/pnAsyncCoreExe/Private/Unix/pnAceUx.h included more than once"
#endif
#define PLASMA20_SOURCES_PLASMA_NUCLEUSLIB_PNASYNCCOREEXE_PRIVATE_UNIX_PNACEUX_H
#ifdef HS_BUILD_FOR_UNIX
/****************************************************************************
*
* Win9x API functions
*
***/
void UxGetApi (AsyncApi * api);
#endif // HS_BUILD_FOR_UNIX
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
/*****************************************************************************
*
* $/Plasma20/Sources/Plasma/NucleusLib/pnAsyncCoreExe/Private/Unix/pnAceUx.h
*
***/
#ifdef PLASMA20_SOURCES_PLASMA_NUCLEUSLIB_PNASYNCCOREEXE_PRIVATE_UNIX_PNACEUX_H
#error "Header $/Plasma20/Sources/Plasma/NucleusLib/pnAsyncCoreExe/Private/Unix/pnAceUx.h included more than once"
#endif
#define PLASMA20_SOURCES_PLASMA_NUCLEUSLIB_PNASYNCCOREEXE_PRIVATE_UNIX_PNACEUX_H
#ifdef HS_BUILD_FOR_UNIX
/****************************************************************************
*
* Win9x API functions
*
***/
void UxGetApi (AsyncApi * api);
#endif // HS_BUILD_FOR_UNIX

View File

@ -1,75 +1,75 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
/*****************************************************************************
*
* $/Plasma20/Sources/Plasma/NucleusLib/pnAsyncCoreExe/Private/W9x/pnAceW9x.cpp
*
***/
#include "../../Pch.h"
#pragma hdrstop
#include "pnAceW9xInt.h"
/****************************************************************************
*
* Exported functions
*
***/
//===========================================================================
void W9xGetApi (AsyncApi * api) {
using namespace W9x;
api->initialize = W9xThreadInitialize;
api->destroy = W9xThreadDestroy;
api->signalShutdown = W9xThreadSignalShutdown;
api->waitForShutdown = W9xThreadWaitForShutdown;
api->sleep = W9xThreadSleep;
api->fileOpen = W9xFileOpen;
api->fileClose = W9xFileClose;
api->fileRead = W9xFileRead;
api->fileWrite = W9xFileWrite;
api->fileFlushBuffers = W9xFileFlushBuffers;
api->fileSetLastWriteTime = W9xFileSetLastWriteTime;
api->fileGetLastWriteTime = W9xFileGetLastWriteTime;
api->fileCreateSequence = W9xFileCreateSequence;
api->fileSeek = W9xFileSeek;
api->socketConnect = W9xSocketConnect;
api->socketConnectCancel = W9xSocketConnectCancel;
api->socketDisconnect = W9xSocketDisconnect;
api->socketDelete = W9xSocketDelete;
api->socketSend = W9xSocketSend;
api->socketWrite = W9xSocketWrite;
api->socketSetNotifyProc = W9xSocketSetNotifyProc;
api->socketSetBacklogAlloc = W9xSocketSetBacklogAlloc;
api->socketStartListening = W9xSocketStartListening;
api->socketStopListening = W9xSocketStopListening;
api->socketEnableNagling = W9xSocketEnableNagling;
}
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
/*****************************************************************************
*
* $/Plasma20/Sources/Plasma/NucleusLib/pnAsyncCoreExe/Private/W9x/pnAceW9x.cpp
*
***/
#include "../../Pch.h"
#pragma hdrstop
#include "pnAceW9xInt.h"
/****************************************************************************
*
* Exported functions
*
***/
//===========================================================================
void W9xGetApi (AsyncApi * api) {
using namespace W9x;
api->initialize = W9xThreadInitialize;
api->destroy = W9xThreadDestroy;
api->signalShutdown = W9xThreadSignalShutdown;
api->waitForShutdown = W9xThreadWaitForShutdown;
api->sleep = W9xThreadSleep;
api->fileOpen = W9xFileOpen;
api->fileClose = W9xFileClose;
api->fileRead = W9xFileRead;
api->fileWrite = W9xFileWrite;
api->fileFlushBuffers = W9xFileFlushBuffers;
api->fileSetLastWriteTime = W9xFileSetLastWriteTime;
api->fileGetLastWriteTime = W9xFileGetLastWriteTime;
api->fileCreateSequence = W9xFileCreateSequence;
api->fileSeek = W9xFileSeek;
api->socketConnect = W9xSocketConnect;
api->socketConnectCancel = W9xSocketConnectCancel;
api->socketDisconnect = W9xSocketDisconnect;
api->socketDelete = W9xSocketDelete;
api->socketSend = W9xSocketSend;
api->socketWrite = W9xSocketWrite;
api->socketSetNotifyProc = W9xSocketSetNotifyProc;
api->socketSetBacklogAlloc = W9xSocketSetBacklogAlloc;
api->socketStartListening = W9xSocketStartListening;
api->socketStopListening = W9xSocketStopListening;
api->socketEnableNagling = W9xSocketEnableNagling;
}

View File

@ -1,48 +1,48 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
/*****************************************************************************
*
* $/Plasma20/Sources/Plasma/NucleusLib/pnAsyncCoreExe/Private/W9x/pnAceW9x.h
*
***/
#ifdef PLASMA20_SOURCES_PLASMA_NUCLEUSLIB_PNASYNCCOREEXE_PRIVATE_W9X_PNACEW9X_H
#error "Header $/Plasma20/Sources/Plasma/NucleusLib/pnAsyncCoreExe/Private/W9x/pnAceW9x.h included more than once"
#endif
#define PLASMA20_SOURCES_PLASMA_NUCLEUSLIB_PNASYNCCOREEXE_PRIVATE_W9X_PNACEW9X_H
#ifdef HS_BUILD_FOR_WIN32
/****************************************************************************
*
* Win9x API functions
*
***/
void W9xGetApi (AsyncApi * api);
#endif // HS_BUILD_FOR_WIN32
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
/*****************************************************************************
*
* $/Plasma20/Sources/Plasma/NucleusLib/pnAsyncCoreExe/Private/W9x/pnAceW9x.h
*
***/
#ifdef PLASMA20_SOURCES_PLASMA_NUCLEUSLIB_PNASYNCCOREEXE_PRIVATE_W9X_PNACEW9X_H
#error "Header $/Plasma20/Sources/Plasma/NucleusLib/pnAsyncCoreExe/Private/W9x/pnAceW9x.h included more than once"
#endif
#define PLASMA20_SOURCES_PLASMA_NUCLEUSLIB_PNASYNCCOREEXE_PRIVATE_W9X_PNACEW9X_H
#ifdef HS_BUILD_FOR_WIN32
/****************************************************************************
*
* Win9x API functions
*
***/
void W9xGetApi (AsyncApi * api);
#endif // HS_BUILD_FOR_WIN32

View File

@ -1,181 +1,181 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
/*****************************************************************************
*
* $/Plasma20/Sources/Plasma/NucleusLib/pnAsyncCoreExe/Private/W9x/pnAceW9xInt.h
*
***/
#ifdef PLASMA20_SOURCES_PLASMA_NUCLEUSLIB_PNASYNCCOREEXE_PRIVATE_W9X_PNACEW9XINT_H
#error "Header $/Plasma20/Sources/Plasma/NucleusLib/pnAsyncCoreExe/Private/W9x/pnAceW9xInt.h included more than once"
#endif
#define PLASMA20_SOURCES_PLASMA_NUCLEUSLIB_PNASYNCCOREEXE_PRIVATE_W9X_PNACEW9XINT_H
namespace W9x {
/*****************************************************************************
*
* Internal types
*
***/
class CThreadDispObject : public AtomicRef {
public:
CThreadDispObject ();
virtual ~CThreadDispObject () { }
void Close ();
virtual void Complete (void * op, CCritSect * critSect, AsyncId asyncId) = 0;
virtual void Delete (void * op) = 0;
AsyncId Queue (void * op);
};
/*****************************************************************************
*
* W9x internal async API
*
***/
void W9xThreadInitialize ();
void W9xThreadDestroy (unsigned exitThreadWaitMs);
void W9xThreadSignalShutdown ();
void W9xThreadWaitForShutdown ();
void W9xThreadSleep (unsigned sleepMs);
bool W9xThreadWaitId (
AsyncFile file,
AsyncId asyncId,
unsigned timeoutMs
);
AsyncFile W9xFileOpen (
const wchar fullPath[],
FAsyncNotifyFileProc notifyProc,
EFileError * error,
unsigned desiredAccess,
unsigned openMode,
unsigned shareModeFlags,
void * userState,
qword * fileSize,
qword * fileLastWriteTime
);
void W9xFileClose (
AsyncFile file,
qword truncateSize
);
void W9xFileSetLastWriteTime (
AsyncFile file,
qword lastWriteTime
);
qword W9xFileGetLastWriteTime (
const wchar fileName[]
);
AsyncId W9xFileFlushBuffers (
AsyncFile file,
qword truncateSize,
bool notify,
void * param
);
AsyncId W9xFileRead (
AsyncFile file,
qword offset,
void * buffer,
unsigned bytes,
unsigned flags,
void * param
);
AsyncId W9xFileWrite (
AsyncFile file,
qword offset,
const void *buffer,
unsigned bytes,
unsigned flags,
void * param
);
AsyncId W9xFileCreateSequence (
AsyncFile file,
bool notify,
void * param
);
bool W9xFileSeek (
AsyncFile file,
qword distance,
EFileSeekFrom from
);
void W9xSocketConnect (
AsyncCancelId * cancelId,
const NetAddress & netAddr,
FAsyncNotifySocketProc notifyProc,
void * param,
const void * sendData,
unsigned sendBytes,
unsigned connectMs,
unsigned localPort
);
void W9xSocketConnectCancel (
FAsyncNotifySocketProc notifyProc,
AsyncCancelId cancelId
);
void W9xSocketDisconnect (
AsyncSocket sock,
bool hardClose
);
void W9xSocketDelete (AsyncSocket sock);
void W9xSocketDestroy ();
bool W9xSocketSend (
AsyncSocket sock,
const void * data,
unsigned bytes
);
bool W9xSocketWrite (
AsyncSocket sock,
const void * buffer,
unsigned bytes,
void * param
);
void W9xSocketSetNotifyProc (
AsyncSocket sock,
FAsyncNotifySocketProc notifyProc
);
void W9xSocketSetBacklogAlloc (
AsyncSocket sock,
unsigned bufferSize
);
unsigned W9xSocketStartListening (
const NetAddress & listenAddr,
FAsyncNotifySocketProc notifyProc
);
void W9xSocketStopListening (
const NetAddress & listenAddr,
FAsyncNotifySocketProc notifyProc
);
void W9xSocketEnableNagling (
AsyncSocket conn,
bool enable
);
} // namespace W9x
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
/*****************************************************************************
*
* $/Plasma20/Sources/Plasma/NucleusLib/pnAsyncCoreExe/Private/W9x/pnAceW9xInt.h
*
***/
#ifdef PLASMA20_SOURCES_PLASMA_NUCLEUSLIB_PNASYNCCOREEXE_PRIVATE_W9X_PNACEW9XINT_H
#error "Header $/Plasma20/Sources/Plasma/NucleusLib/pnAsyncCoreExe/Private/W9x/pnAceW9xInt.h included more than once"
#endif
#define PLASMA20_SOURCES_PLASMA_NUCLEUSLIB_PNASYNCCOREEXE_PRIVATE_W9X_PNACEW9XINT_H
namespace W9x {
/*****************************************************************************
*
* Internal types
*
***/
class CThreadDispObject : public AtomicRef {
public:
CThreadDispObject ();
virtual ~CThreadDispObject () { }
void Close ();
virtual void Complete (void * op, CCritSect * critSect, AsyncId asyncId) = 0;
virtual void Delete (void * op) = 0;
AsyncId Queue (void * op);
};
/*****************************************************************************
*
* W9x internal async API
*
***/
void W9xThreadInitialize ();
void W9xThreadDestroy (unsigned exitThreadWaitMs);
void W9xThreadSignalShutdown ();
void W9xThreadWaitForShutdown ();
void W9xThreadSleep (unsigned sleepMs);
bool W9xThreadWaitId (
AsyncFile file,
AsyncId asyncId,
unsigned timeoutMs
);
AsyncFile W9xFileOpen (
const wchar fullPath[],
FAsyncNotifyFileProc notifyProc,
EFileError * error,
unsigned desiredAccess,
unsigned openMode,
unsigned shareModeFlags,
void * userState,
qword * fileSize,
qword * fileLastWriteTime
);
void W9xFileClose (
AsyncFile file,
qword truncateSize
);
void W9xFileSetLastWriteTime (
AsyncFile file,
qword lastWriteTime
);
qword W9xFileGetLastWriteTime (
const wchar fileName[]
);
AsyncId W9xFileFlushBuffers (
AsyncFile file,
qword truncateSize,
bool notify,
void * param
);
AsyncId W9xFileRead (
AsyncFile file,
qword offset,
void * buffer,
unsigned bytes,
unsigned flags,
void * param
);
AsyncId W9xFileWrite (
AsyncFile file,
qword offset,
const void *buffer,
unsigned bytes,
unsigned flags,
void * param
);
AsyncId W9xFileCreateSequence (
AsyncFile file,
bool notify,
void * param
);
bool W9xFileSeek (
AsyncFile file,
qword distance,
EFileSeekFrom from
);
void W9xSocketConnect (
AsyncCancelId * cancelId,
const NetAddress & netAddr,
FAsyncNotifySocketProc notifyProc,
void * param,
const void * sendData,
unsigned sendBytes,
unsigned connectMs,
unsigned localPort
);
void W9xSocketConnectCancel (
FAsyncNotifySocketProc notifyProc,
AsyncCancelId cancelId
);
void W9xSocketDisconnect (
AsyncSocket sock,
bool hardClose
);
void W9xSocketDelete (AsyncSocket sock);
void W9xSocketDestroy ();
bool W9xSocketSend (
AsyncSocket sock,
const void * data,
unsigned bytes
);
bool W9xSocketWrite (
AsyncSocket sock,
const void * buffer,
unsigned bytes,
void * param
);
void W9xSocketSetNotifyProc (
AsyncSocket sock,
FAsyncNotifySocketProc notifyProc
);
void W9xSocketSetBacklogAlloc (
AsyncSocket sock,
unsigned bufferSize
);
unsigned W9xSocketStartListening (
const NetAddress & listenAddr,
FAsyncNotifySocketProc notifyProc
);
void W9xSocketStopListening (
const NetAddress & listenAddr,
FAsyncNotifySocketProc notifyProc
);
void W9xSocketEnableNagling (
AsyncSocket conn,
bool enable
);
} // namespace W9x

View File

@ -1,435 +1,435 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
/*****************************************************************************
*
* $/Plasma20/Sources/Plasma/NucleusLib/pnAsyncCoreExe/Private/W9x/pnAceW9xThread.cpp
*
***/
#include "../../Pch.h"
#pragma hdrstop
#include "pnAceW9xInt.h"
namespace W9x {
/*****************************************************************************
*
* Private data
*
***/
const unsigned kThreadCount = 2;
static CCritSect s_critSect;
static bool s_destroying;
static HANDLE s_destroyEvent;
static unsigned s_sequence;
static HANDLE s_shutdownEvent;
static HANDLE s_signalEvent;
static HANDLE s_thread[kThreadCount];
/****************************************************************************
*
* ThreadWaitRec
*
***/
struct ThreadWaitRec {
HANDLE event;
LINK(ThreadWaitRec) link;
};
/****************************************************************************
*
* CThreadDispRec
*
***/
class CThreadDispRec {
private:
CThreadDispObject * m_object;
void * m_op;
AsyncId m_ioId;
LISTDECL(ThreadWaitRec, link) m_waitList;
public:
LINK(CThreadDispRec) m_link;
CThreadDispRec (
CThreadDispObject * object,
void * op,
AsyncId * asyncId
);
~CThreadDispRec ();
void Complete (CCritSect * critSect);
AsyncId GetId () const { return m_ioId; }
void LinkWait (ThreadWaitRec * wait);
};
static LISTDECL(CThreadDispRec, m_link) s_dispList;
static LISTDECL(CThreadDispRec, m_link) s_dispInProcList;
//===========================================================================
CThreadDispRec::CThreadDispRec (
CThreadDispObject * object,
void * op,
AsyncId * asyncId
) :
m_object(object),
m_op(op)
{
s_critSect.Enter();
// Verify that this module is not being destroyed
ASSERT(!s_destroying);
// Increment the owning object's reference count
object->IncRef();
// Assign an id
m_ioId = (AsyncId)++s_sequence;
if (!m_ioId)
m_ioId = (AsyncId)++s_sequence;
*asyncId = m_ioId;
// Link this record to the dispatch list
s_dispList.Link(this);
s_critSect.Leave();
}
//===========================================================================
CThreadDispRec::~CThreadDispRec () {
// Delete the operation data
CThreadDispObject * object = m_object;
object->Delete(m_op);
s_critSect.Enter();
// Unlink this record
m_link.Unlink();
// Wake up all threads blocking on this operation. We must unlink each
// wait record before we signal it.
for (ThreadWaitRec * rec; (rec = m_waitList.Head()) != nil; ) {
m_waitList.Unlink(rec);
SetEvent(rec->event);
}
// Decrement the owning object's reference count
object->DecRef();
s_critSect.Leave();
}
//===========================================================================
void CThreadDispRec::Complete (CCritSect * critSect) {
m_object->Complete(m_op, critSect, m_ioId);
}
//===========================================================================
void CThreadDispRec::LinkWait (ThreadWaitRec * wait) {
// The caller should have already claimed the critical section before
// calling this function
m_waitList.Link(wait);
}
/****************************************************************************
*
* CThreadDispObject
*
***/
//===========================================================================
CThreadDispObject::CThreadDispObject () {
IncRef();
}
//===========================================================================
void CThreadDispObject::Close () {
s_critSect.Enter();
DecRef();
s_critSect.Leave();
}
//===========================================================================
AsyncId CThreadDispObject::Queue (void * op) {
AsyncId asyncId = 0;
NEW(CThreadDispRec)(this, op, &asyncId);
SetEvent(s_signalEvent);
return asyncId;
}
/****************************************************************************
*
* Thread procedure
*
***/
//===========================================================================
static unsigned CALLBACK W9xThreadProc (AsyncThread *) {
// Perform the main thread loop
for (;;) {
unsigned timeout = (unsigned)-1;
// If an operation is queued, complete it and dispatch a notification.
// The code that processes the operation is responsible for leaving
// our critical section. This ensures that operations are completed
// in order.
s_critSect.Enter();
CThreadDispRec * rec = s_dispList.Head();
if (rec) {
s_dispInProcList.Link(rec);
rec->Complete(&s_critSect);
DEL(rec);
timeout = 0;
}
else {
s_critSect.Leave();
}
// Consume events, check for destruction, and block if we have
// nothing to do.
HANDLE events[] = {s_destroyEvent, s_signalEvent};
dword result = WaitForMultipleObjects(
arrsize(events),
events,
FALSE,
INFINITE
);
if (result == WAIT_OBJECT_0)
return 0;
}
}
/****************************************************************************
*
* Exported functions
*
***/
//===========================================================================
void W9xThreadDestroy (
unsigned exitThreadWaitMs
) {
// Wait until all outstanding I/O is complete. We allow new I/O
// operations to be queued while old ones are completing.
s_critSect.Enter();
while (s_dispList.Head() || s_dispInProcList.Head()) {
s_critSect.Leave();
Sleep(10);
s_critSect.Enter();
}
// Once all I/O operations are complete, we disallow any future
// I/O operations from being queued.
s_destroying = true;
s_critSect.Leave();
// Signal thread destruction
if (s_destroyEvent)
SetEvent(s_destroyEvent);
// Wait for thread destruction
for (unsigned thread = kThreadCount; thread--; )
if (s_thread[thread]) {
// Wait for the thread to terminate
WaitForSingleObject(s_thread[thread], exitThreadWaitMs);
// Close the thread handle
CloseHandle(s_thread[thread]);
s_thread[thread] = 0;
}
// Destroy internal modules
W9xSocketDestroy();
// Destroy events
if (s_destroyEvent) {
CloseHandle(s_destroyEvent);
s_destroyEvent = 0;
}
if (s_shutdownEvent) {
CloseHandle(s_shutdownEvent);
s_shutdownEvent = 0;
}
if (s_signalEvent) {
CloseHandle(s_signalEvent);
s_signalEvent = 0;
}
}
//===========================================================================
void W9xThreadInitialize () {
// Reset static variables
s_destroying = false;
// Create a manual reset event to use for signaling thread destruction
if (s_destroyEvent)
ResetEvent(s_destroyEvent);
else {
s_destroyEvent = CreateEvent(nil, TRUE, FALSE, nil);
ASSERT(s_destroyEvent);
}
// Create an auto-reset event to use for signaling the thread to process
// notifications
if (!s_signalEvent) {
s_signalEvent = CreateEvent(nil, FALSE, FALSE, nil);
ASSERT(s_signalEvent);
}
// Create a manual reset event to use for signaling application shutdown
if (s_shutdownEvent)
ResetEvent(s_shutdownEvent);
else {
s_shutdownEvent = CreateEvent(nil, TRUE, FALSE, nil);
ASSERT(s_shutdownEvent);
}
// Create threads
for (unsigned thread = 0; thread < kThreadCount; ++thread) {
if (!s_thread[thread]) {
s_thread[thread] = (HANDLE) AsyncThreadCreate(
W9xThreadProc,
(void *) thread,
L"W9xWorkerThread"
);
}
}
}
//===========================================================================
void W9xThreadSignalShutdown () {
SetEvent(s_shutdownEvent);
}
//===========================================================================
void W9xThreadSleep (
unsigned sleepMs
) {
Sleep(sleepMs);
}
//===========================================================================
void W9xThreadWaitForShutdown () {
// We know that the applicaton is finished initializing at this point.
// While it was still initializing, it may have returned an infinite
// sleep time from the idle procedure, which would prevent us from ever
// calling it again. Therefore, we trigger an idle callback here.
SetEvent(s_signalEvent);
// Wait for the application to signal shutdown
WaitForSingleObject(s_shutdownEvent, INFINITE);
}
//===========================================================================
bool W9xThreadWaitId (
AsyncFile file,
AsyncId asyncId,
unsigned timeoutMs
) {
// Find a pending I/O operation with the given id
s_critSect.Enter();
CThreadDispRec * disp;
for (disp = s_dispList.Head(); disp && (disp->GetId() != asyncId); disp = s_dispList.Next(disp))
;
if (!disp)
for (disp = s_dispInProcList.Head(); disp && (disp->GetId() != asyncId); disp = s_dispInProcList.Next(disp))
;
// If we couldn't find the given id, the operation must have already
// completed, so return true.
if (!disp) {
s_critSect.Leave();
return true;
}
// The operation has not completed. If the timeout is zero, return
// false.
if (!timeoutMs) {
s_critSect.Leave();
return false;
}
// Create a wait event
HANDLE event = CreateEvent(nil, FALSE, FALSE, nil);
// Create a wait record and link it to the I/O operation
ThreadWaitRec wait;
wait.event = event;
disp->LinkWait(&wait);
s_critSect.Leave();
// Wait for the operation to complete
DWORD result = WaitForSingleObject(event, timeoutMs);
// If the operation completed then the dispatcher unlinked our wait
// record before signaling it. We can simply free the event and return.
if (result == WAIT_OBJECT_0) {
CloseHandle(event);
return true;
}
// Unlink our wait record from the I/O operation
s_critSect.Enter();
wait.link.Unlink();
s_critSect.Leave();
// Free the event
CloseHandle(event);
// Return false, because the operation did not complete during the
// timeout period
return false;
}
} // namespace W9x
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
/*****************************************************************************
*
* $/Plasma20/Sources/Plasma/NucleusLib/pnAsyncCoreExe/Private/W9x/pnAceW9xThread.cpp
*
***/
#include "../../Pch.h"
#pragma hdrstop
#include "pnAceW9xInt.h"
namespace W9x {
/*****************************************************************************
*
* Private data
*
***/
const unsigned kThreadCount = 2;
static CCritSect s_critSect;
static bool s_destroying;
static HANDLE s_destroyEvent;
static unsigned s_sequence;
static HANDLE s_shutdownEvent;
static HANDLE s_signalEvent;
static HANDLE s_thread[kThreadCount];
/****************************************************************************
*
* ThreadWaitRec
*
***/
struct ThreadWaitRec {
HANDLE event;
LINK(ThreadWaitRec) link;
};
/****************************************************************************
*
* CThreadDispRec
*
***/
class CThreadDispRec {
private:
CThreadDispObject * m_object;
void * m_op;
AsyncId m_ioId;
LISTDECL(ThreadWaitRec, link) m_waitList;
public:
LINK(CThreadDispRec) m_link;
CThreadDispRec (
CThreadDispObject * object,
void * op,
AsyncId * asyncId
);
~CThreadDispRec ();
void Complete (CCritSect * critSect);
AsyncId GetId () const { return m_ioId; }
void LinkWait (ThreadWaitRec * wait);
};
static LISTDECL(CThreadDispRec, m_link) s_dispList;
static LISTDECL(CThreadDispRec, m_link) s_dispInProcList;
//===========================================================================
CThreadDispRec::CThreadDispRec (
CThreadDispObject * object,
void * op,
AsyncId * asyncId
) :
m_object(object),
m_op(op)
{
s_critSect.Enter();
// Verify that this module is not being destroyed
ASSERT(!s_destroying);
// Increment the owning object's reference count
object->IncRef();
// Assign an id
m_ioId = (AsyncId)++s_sequence;
if (!m_ioId)
m_ioId = (AsyncId)++s_sequence;
*asyncId = m_ioId;
// Link this record to the dispatch list
s_dispList.Link(this);
s_critSect.Leave();
}
//===========================================================================
CThreadDispRec::~CThreadDispRec () {
// Delete the operation data
CThreadDispObject * object = m_object;
object->Delete(m_op);
s_critSect.Enter();
// Unlink this record
m_link.Unlink();
// Wake up all threads blocking on this operation. We must unlink each
// wait record before we signal it.
for (ThreadWaitRec * rec; (rec = m_waitList.Head()) != nil; ) {
m_waitList.Unlink(rec);
SetEvent(rec->event);
}
// Decrement the owning object's reference count
object->DecRef();
s_critSect.Leave();
}
//===========================================================================
void CThreadDispRec::Complete (CCritSect * critSect) {
m_object->Complete(m_op, critSect, m_ioId);
}
//===========================================================================
void CThreadDispRec::LinkWait (ThreadWaitRec * wait) {
// The caller should have already claimed the critical section before
// calling this function
m_waitList.Link(wait);
}
/****************************************************************************
*
* CThreadDispObject
*
***/
//===========================================================================
CThreadDispObject::CThreadDispObject () {
IncRef();
}
//===========================================================================
void CThreadDispObject::Close () {
s_critSect.Enter();
DecRef();
s_critSect.Leave();
}
//===========================================================================
AsyncId CThreadDispObject::Queue (void * op) {
AsyncId asyncId = 0;
NEW(CThreadDispRec)(this, op, &asyncId);
SetEvent(s_signalEvent);
return asyncId;
}
/****************************************************************************
*
* Thread procedure
*
***/
//===========================================================================
static unsigned CALLBACK W9xThreadProc (AsyncThread *) {
// Perform the main thread loop
for (;;) {
unsigned timeout = (unsigned)-1;
// If an operation is queued, complete it and dispatch a notification.
// The code that processes the operation is responsible for leaving
// our critical section. This ensures that operations are completed
// in order.
s_critSect.Enter();
CThreadDispRec * rec = s_dispList.Head();
if (rec) {
s_dispInProcList.Link(rec);
rec->Complete(&s_critSect);
DEL(rec);
timeout = 0;
}
else {
s_critSect.Leave();
}
// Consume events, check for destruction, and block if we have
// nothing to do.
HANDLE events[] = {s_destroyEvent, s_signalEvent};
dword result = WaitForMultipleObjects(
arrsize(events),
events,
FALSE,
INFINITE
);
if (result == WAIT_OBJECT_0)
return 0;
}
}
/****************************************************************************
*
* Exported functions
*
***/
//===========================================================================
void W9xThreadDestroy (
unsigned exitThreadWaitMs
) {
// Wait until all outstanding I/O is complete. We allow new I/O
// operations to be queued while old ones are completing.
s_critSect.Enter();
while (s_dispList.Head() || s_dispInProcList.Head()) {
s_critSect.Leave();
Sleep(10);
s_critSect.Enter();
}
// Once all I/O operations are complete, we disallow any future
// I/O operations from being queued.
s_destroying = true;
s_critSect.Leave();
// Signal thread destruction
if (s_destroyEvent)
SetEvent(s_destroyEvent);
// Wait for thread destruction
for (unsigned thread = kThreadCount; thread--; )
if (s_thread[thread]) {
// Wait for the thread to terminate
WaitForSingleObject(s_thread[thread], exitThreadWaitMs);
// Close the thread handle
CloseHandle(s_thread[thread]);
s_thread[thread] = 0;
}
// Destroy internal modules
W9xSocketDestroy();
// Destroy events
if (s_destroyEvent) {
CloseHandle(s_destroyEvent);
s_destroyEvent = 0;
}
if (s_shutdownEvent) {
CloseHandle(s_shutdownEvent);
s_shutdownEvent = 0;
}
if (s_signalEvent) {
CloseHandle(s_signalEvent);
s_signalEvent = 0;
}
}
//===========================================================================
void W9xThreadInitialize () {
// Reset static variables
s_destroying = false;
// Create a manual reset event to use for signaling thread destruction
if (s_destroyEvent)
ResetEvent(s_destroyEvent);
else {
s_destroyEvent = CreateEvent(nil, TRUE, FALSE, nil);
ASSERT(s_destroyEvent);
}
// Create an auto-reset event to use for signaling the thread to process
// notifications
if (!s_signalEvent) {
s_signalEvent = CreateEvent(nil, FALSE, FALSE, nil);
ASSERT(s_signalEvent);
}
// Create a manual reset event to use for signaling application shutdown
if (s_shutdownEvent)
ResetEvent(s_shutdownEvent);
else {
s_shutdownEvent = CreateEvent(nil, TRUE, FALSE, nil);
ASSERT(s_shutdownEvent);
}
// Create threads
for (unsigned thread = 0; thread < kThreadCount; ++thread) {
if (!s_thread[thread]) {
s_thread[thread] = (HANDLE) AsyncThreadCreate(
W9xThreadProc,
(void *) thread,
L"W9xWorkerThread"
);
}
}
}
//===========================================================================
void W9xThreadSignalShutdown () {
SetEvent(s_shutdownEvent);
}
//===========================================================================
void W9xThreadSleep (
unsigned sleepMs
) {
Sleep(sleepMs);
}
//===========================================================================
void W9xThreadWaitForShutdown () {
// We know that the applicaton is finished initializing at this point.
// While it was still initializing, it may have returned an infinite
// sleep time from the idle procedure, which would prevent us from ever
// calling it again. Therefore, we trigger an idle callback here.
SetEvent(s_signalEvent);
// Wait for the application to signal shutdown
WaitForSingleObject(s_shutdownEvent, INFINITE);
}
//===========================================================================
bool W9xThreadWaitId (
AsyncFile file,
AsyncId asyncId,
unsigned timeoutMs
) {
// Find a pending I/O operation with the given id
s_critSect.Enter();
CThreadDispRec * disp;
for (disp = s_dispList.Head(); disp && (disp->GetId() != asyncId); disp = s_dispList.Next(disp))
;
if (!disp)
for (disp = s_dispInProcList.Head(); disp && (disp->GetId() != asyncId); disp = s_dispInProcList.Next(disp))
;
// If we couldn't find the given id, the operation must have already
// completed, so return true.
if (!disp) {
s_critSect.Leave();
return true;
}
// The operation has not completed. If the timeout is zero, return
// false.
if (!timeoutMs) {
s_critSect.Leave();
return false;
}
// Create a wait event
HANDLE event = CreateEvent(nil, FALSE, FALSE, nil);
// Create a wait record and link it to the I/O operation
ThreadWaitRec wait;
wait.event = event;
disp->LinkWait(&wait);
s_critSect.Leave();
// Wait for the operation to complete
DWORD result = WaitForSingleObject(event, timeoutMs);
// If the operation completed then the dispatcher unlinked our wait
// record before signaling it. We can simply free the event and return.
if (result == WAIT_OBJECT_0) {
CloseHandle(event);
return true;
}
// Unlink our wait record from the I/O operation
s_critSect.Enter();
wait.link.Unlink();
s_critSect.Leave();
// Free the event
CloseHandle(event);
// Return false, because the operation did not complete during the
// timeout period
return false;
}
} // namespace W9x

View File

@ -1,384 +1,384 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
/*****************************************************************************
*
* $/Plasma20/Sources/Plasma/NucleusLib/pnAsyncCoreExe/Private/Win32/pnAceW32Dns.cpp
*
***/
#include "../../Pch.h"
#pragma hdrstop
/*****************************************************************************
*
* Private
*
***/
enum {
WM_LOOKUP_EXIT = WM_APP,
WM_LOOKUP_FOUND_HOST
};
const unsigned kMaxLookupName = 128;
struct Lookup {
LINK(Lookup) link;
AsyncCancelId cancelId;
HANDLE cancelHandle;
FAsyncLookupProc lookupProc;
unsigned port;
void * param;
wchar name[kMaxLookupName];
char buffer[MAXGETHOSTSTRUCT];
};
static CCritSect s_critsect;
static LISTDECL(Lookup, link) s_lookupList;
static HANDLE s_lookupThread;
static HWND s_lookupWindow;
static unsigned s_nextLookupCancelId = 1;
/*****************************************************************************
*
* Internal functions
*
***/
//===========================================================================
static void LookupProcess (Lookup * lookup, unsigned error) {
unsigned count = 0;
NetAddress * addrs = nil;
for (ONCE) {
if (error)
break;
const HOSTENT & host = * (HOSTENT *) lookup->buffer;
if (host.h_addrtype != AF_INET)
break;
if (host.h_length != sizeof(in_addr))
break;
if (!host.h_addr_list)
break;
in_addr const * const * const inAddr = (in_addr **) host.h_addr_list;
// count the number of addresses
while (inAddr[count])
++count;
// allocate a buffer large enough to hold all the addresses
addrs = (NetAddress *) _alloca(sizeof(*addrs) * count);
MemZero(addrs, sizeof(*addrs) * count);
// fill in address data
const word port = htons((word) lookup->port);
for (unsigned i = 0; i < count; ++i) {
sockaddr_in * inetaddr = (sockaddr_in *) &addrs[i];
inetaddr->sin_family = AF_INET;
inetaddr->sin_addr = *inAddr[i];
inetaddr->sin_port = port;
}
if (host.h_name && host.h_name[0])
StrToUnicode(lookup->name, host.h_name, arrsize(lookup->name));
}
if (lookup->lookupProc)
lookup->lookupProc(lookup->param, lookup->name, count, addrs);
// we can delete the operation outside an IoConn critical
// section because it isn't linked into an ioConn opList
// and because connection attempts are not waitable
ASSERT(!lookup->link.IsLinked());
DEL(lookup);
PerfSubCounter(kAsyncPerfNameLookupAttemptsCurr, 1);
}
//===========================================================================
static void LookupFindAndProcess (HANDLE cancelHandle, unsigned error) {
// find the operation for this cancel handle
Lookup * lookup;
s_critsect.Enter();
for (lookup = s_lookupList.Head(); lookup; lookup = s_lookupList.Next(lookup)) {
if (lookup->cancelHandle == cancelHandle) {
lookup->cancelHandle = nil;
s_lookupList.Unlink(lookup);
break;
}
}
s_critsect.Leave();
if (lookup)
LookupProcess(lookup, error);
}
//===========================================================================
static unsigned THREADCALL LookupThreadProc (AsyncThread * thread) {
static const char WINDOW_CLASS[] = "AsyncLookupWnd";
WNDCLASS wc;
ZERO(wc);
wc.lpfnWndProc = DefWindowProc;
wc.hInstance = GetModuleHandle(0);
wc.lpszClassName = WINDOW_CLASS;
RegisterClass(&wc);
s_lookupWindow = CreateWindow(
WINDOW_CLASS,
WINDOW_CLASS,
WS_OVERLAPPED,
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
(HWND)0,
(HMENU) 0,
wc.hInstance,
0
);
if (!s_lookupWindow)
ErrorFatal(__LINE__, __FILE__, "CreateWindow %#x", GetLastError());
HANDLE lookupStartEvent = (HANDLE) thread->argument;
SetEvent(lookupStartEvent);
MSG msg;
while (GetMessage(&msg, s_lookupWindow, 0, 0)) {
if (msg.message == WM_LOOKUP_FOUND_HOST)
LookupFindAndProcess((HANDLE) msg.wParam, HIWORD(msg.lParam));
else if (msg.message == WM_LOOKUP_EXIT)
break;
else {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
// fail all pending name lookups
for (;;) {
s_critsect.Enter();
Lookup * lookup = s_lookupList.Head();
if (lookup) {
WSACancelAsyncRequest(lookup->cancelHandle);
lookup->cancelHandle = nil;
s_lookupList.Unlink(lookup);
}
s_critsect.Leave();
if (!lookup)
break;
LookupProcess(lookup, (unsigned) -1);
}
// cleanup
DestroyWindow(s_lookupWindow);
s_lookupWindow = nil;
return 0;
}
//===========================================================================
static void StartLookupThread () {
if (s_lookupThread)
return;
// create a shutdown event
HANDLE lookupStartEvent = CreateEvent(
(LPSECURITY_ATTRIBUTES) 0,
true, // manual reset
false, // initial state off
(LPCTSTR) 0 // name
);
if (!lookupStartEvent)
ErrorFatal(__LINE__, __FILE__, "CreateEvent %#x", GetLastError());
// create a thread to perform lookups
s_lookupThread = (HANDLE) AsyncThreadCreate(
LookupThreadProc,
lookupStartEvent,
L"AsyncLookupThread"
);
WaitForSingleObject(lookupStartEvent, INFINITE);
CloseHandle(lookupStartEvent);
ASSERT(s_lookupWindow);
}
/*****************************************************************************
*
* Module functions
*
***/
//===========================================================================
void DnsDestroy (unsigned exitThreadWaitMs) {
if (s_lookupThread) {
PostMessage(s_lookupWindow, WM_LOOKUP_EXIT, 0, 0);
WaitForSingleObject(s_lookupThread, exitThreadWaitMs);
CloseHandle(s_lookupThread);
s_lookupThread = nil;
ASSERT(!s_lookupWindow);
}
}
/*****************************************************************************
*
* Public functions
*
***/
//===========================================================================
void AsyncAddressLookupName (
AsyncCancelId * cancelId, // out
FAsyncLookupProc lookupProc,
const wchar name[],
unsigned port,
void * param
) {
ASSERT(lookupProc);
ASSERT(name);
PerfAddCounter(kAsyncPerfNameLookupAttemptsCurr, 1);
PerfAddCounter(kAsyncPerfNameLookupAttemptsTotal, 1);
// Get name/port
char ansiName[kMaxLookupName];
StrToAnsi(ansiName, name, arrsize(ansiName));
if (char * portStr = StrChr(ansiName, ':')) {
if (unsigned newPort = StrToUnsigned(portStr + 1, nil, 10))
port = newPort;
*portStr = 0;
}
// Initialize lookup
Lookup * lookup = NEW(Lookup);
lookup->lookupProc = lookupProc;
lookup->port = port;
lookup->param = param;
StrCopy(lookup->name, name, arrsize(lookup->name));
s_critsect.Enter();
{
// Start the lookup thread if it wasn't started already
StartLookupThread();
s_lookupList.Link(lookup);
// get cancel id; we can avoid checking for zero by always using an odd number
ASSERT(s_nextLookupCancelId & 1);
s_nextLookupCancelId += 2;
*cancelId = lookup->cancelId = (AsyncCancelId) s_nextLookupCancelId;
// Perform async lookup
lookup->cancelHandle = WSAAsyncGetHostByName(
s_lookupWindow,
WM_LOOKUP_FOUND_HOST,
ansiName,
&lookup->buffer[0],
sizeof(lookup->buffer)
);
if (!lookup->cancelHandle) {
PostMessage(s_lookupWindow, WM_LOOKUP_FOUND_HOST, nil, (unsigned) -1);
}
}
s_critsect.Leave();
}
//===========================================================================
void AsyncAddressLookupAddr (
AsyncCancelId * cancelId, // out
FAsyncLookupProc lookupProc,
const NetAddress & address,
void * param
) {
ASSERT(lookupProc);
PerfAddCounter(kAsyncPerfNameLookupAttemptsCurr, 1);
PerfAddCounter(kAsyncPerfNameLookupAttemptsTotal, 1);
// Initialize lookup
Lookup * lookup = NEW(Lookup);
lookup->lookupProc = lookupProc;
lookup->port = 1;
lookup->param = param;
NetAddressToString(
address,
lookup->name,
arrsize(lookup->name),
kNetAddressFormatNodeNumber
);
s_critsect.Enter();
{
// Start the lookup thread if it wasn't started already
StartLookupThread();
s_lookupList.Link(lookup);
// get cancel id; we can avoid checking for zero by always using an odd number
ASSERT(s_nextLookupCancelId & 1);
s_nextLookupCancelId += 2;
*cancelId = lookup->cancelId = (AsyncCancelId) s_nextLookupCancelId;
// Perform async lookup
u_long addr = ((const sockaddr_in *) &address)->sin_addr.S_un.S_addr;
lookup->cancelHandle = WSAAsyncGetHostByAddr(
s_lookupWindow,
WM_LOOKUP_FOUND_HOST,
(const char *) &addr,
sizeof(addr),
AF_INET,
&lookup->buffer[0],
sizeof(lookup->buffer)
);
if (!lookup->cancelHandle) {
PostMessage(s_lookupWindow, WM_LOOKUP_FOUND_HOST, nil, (unsigned) -1);
}
}
s_critsect.Leave();
}
//===========================================================================
void AsyncAddressLookupCancel (
FAsyncLookupProc lookupProc,
AsyncCancelId cancelId // nil = cancel all with specified lookupProc
) {
s_critsect.Enter();
for (Lookup * lookup = s_lookupList.Head(); lookup; lookup = s_lookupList.Next(lookup)) {
if (lookup->lookupProc && (lookup->lookupProc != lookupProc))
continue;
if (cancelId && (lookup->cancelId != cancelId))
continue;
if (!lookup->cancelHandle)
continue;
// cancel this request
WSACancelAsyncRequest(lookup->cancelHandle);
lookup->cancelHandle = nil;
// initiate user callback
PostMessage(s_lookupWindow, WM_LOOKUP_FOUND_HOST, nil, (unsigned) -1);
}
s_critsect.Leave();
}
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
/*****************************************************************************
*
* $/Plasma20/Sources/Plasma/NucleusLib/pnAsyncCoreExe/Private/Win32/pnAceW32Dns.cpp
*
***/
#include "../../Pch.h"
#pragma hdrstop
/*****************************************************************************
*
* Private
*
***/
enum {
WM_LOOKUP_EXIT = WM_APP,
WM_LOOKUP_FOUND_HOST
};
const unsigned kMaxLookupName = 128;
struct Lookup {
LINK(Lookup) link;
AsyncCancelId cancelId;
HANDLE cancelHandle;
FAsyncLookupProc lookupProc;
unsigned port;
void * param;
wchar name[kMaxLookupName];
char buffer[MAXGETHOSTSTRUCT];
};
static CCritSect s_critsect;
static LISTDECL(Lookup, link) s_lookupList;
static HANDLE s_lookupThread;
static HWND s_lookupWindow;
static unsigned s_nextLookupCancelId = 1;
/*****************************************************************************
*
* Internal functions
*
***/
//===========================================================================
static void LookupProcess (Lookup * lookup, unsigned error) {
unsigned count = 0;
NetAddress * addrs = nil;
for (ONCE) {
if (error)
break;
const HOSTENT & host = * (HOSTENT *) lookup->buffer;
if (host.h_addrtype != AF_INET)
break;
if (host.h_length != sizeof(in_addr))
break;
if (!host.h_addr_list)
break;
in_addr const * const * const inAddr = (in_addr **) host.h_addr_list;
// count the number of addresses
while (inAddr[count])
++count;
// allocate a buffer large enough to hold all the addresses
addrs = (NetAddress *) _alloca(sizeof(*addrs) * count);
MemZero(addrs, sizeof(*addrs) * count);
// fill in address data
const word port = htons((word) lookup->port);
for (unsigned i = 0; i < count; ++i) {
sockaddr_in * inetaddr = (sockaddr_in *) &addrs[i];
inetaddr->sin_family = AF_INET;
inetaddr->sin_addr = *inAddr[i];
inetaddr->sin_port = port;
}
if (host.h_name && host.h_name[0])
StrToUnicode(lookup->name, host.h_name, arrsize(lookup->name));
}
if (lookup->lookupProc)
lookup->lookupProc(lookup->param, lookup->name, count, addrs);
// we can delete the operation outside an IoConn critical
// section because it isn't linked into an ioConn opList
// and because connection attempts are not waitable
ASSERT(!lookup->link.IsLinked());
DEL(lookup);
PerfSubCounter(kAsyncPerfNameLookupAttemptsCurr, 1);
}
//===========================================================================
static void LookupFindAndProcess (HANDLE cancelHandle, unsigned error) {
// find the operation for this cancel handle
Lookup * lookup;
s_critsect.Enter();
for (lookup = s_lookupList.Head(); lookup; lookup = s_lookupList.Next(lookup)) {
if (lookup->cancelHandle == cancelHandle) {
lookup->cancelHandle = nil;
s_lookupList.Unlink(lookup);
break;
}
}
s_critsect.Leave();
if (lookup)
LookupProcess(lookup, error);
}
//===========================================================================
static unsigned THREADCALL LookupThreadProc (AsyncThread * thread) {
static const char WINDOW_CLASS[] = "AsyncLookupWnd";
WNDCLASS wc;
ZERO(wc);
wc.lpfnWndProc = DefWindowProc;
wc.hInstance = GetModuleHandle(0);
wc.lpszClassName = WINDOW_CLASS;
RegisterClass(&wc);
s_lookupWindow = CreateWindow(
WINDOW_CLASS,
WINDOW_CLASS,
WS_OVERLAPPED,
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
(HWND)0,
(HMENU) 0,
wc.hInstance,
0
);
if (!s_lookupWindow)
ErrorFatal(__LINE__, __FILE__, "CreateWindow %#x", GetLastError());
HANDLE lookupStartEvent = (HANDLE) thread->argument;
SetEvent(lookupStartEvent);
MSG msg;
while (GetMessage(&msg, s_lookupWindow, 0, 0)) {
if (msg.message == WM_LOOKUP_FOUND_HOST)
LookupFindAndProcess((HANDLE) msg.wParam, HIWORD(msg.lParam));
else if (msg.message == WM_LOOKUP_EXIT)
break;
else {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
// fail all pending name lookups
for (;;) {
s_critsect.Enter();
Lookup * lookup = s_lookupList.Head();
if (lookup) {
WSACancelAsyncRequest(lookup->cancelHandle);
lookup->cancelHandle = nil;
s_lookupList.Unlink(lookup);
}
s_critsect.Leave();
if (!lookup)
break;
LookupProcess(lookup, (unsigned) -1);
}
// cleanup
DestroyWindow(s_lookupWindow);
s_lookupWindow = nil;
return 0;
}
//===========================================================================
static void StartLookupThread () {
if (s_lookupThread)
return;
// create a shutdown event
HANDLE lookupStartEvent = CreateEvent(
(LPSECURITY_ATTRIBUTES) 0,
true, // manual reset
false, // initial state off
(LPCTSTR) 0 // name
);
if (!lookupStartEvent)
ErrorFatal(__LINE__, __FILE__, "CreateEvent %#x", GetLastError());
// create a thread to perform lookups
s_lookupThread = (HANDLE) AsyncThreadCreate(
LookupThreadProc,
lookupStartEvent,
L"AsyncLookupThread"
);
WaitForSingleObject(lookupStartEvent, INFINITE);
CloseHandle(lookupStartEvent);
ASSERT(s_lookupWindow);
}
/*****************************************************************************
*
* Module functions
*
***/
//===========================================================================
void DnsDestroy (unsigned exitThreadWaitMs) {
if (s_lookupThread) {
PostMessage(s_lookupWindow, WM_LOOKUP_EXIT, 0, 0);
WaitForSingleObject(s_lookupThread, exitThreadWaitMs);
CloseHandle(s_lookupThread);
s_lookupThread = nil;
ASSERT(!s_lookupWindow);
}
}
/*****************************************************************************
*
* Public functions
*
***/
//===========================================================================
void AsyncAddressLookupName (
AsyncCancelId * cancelId, // out
FAsyncLookupProc lookupProc,
const wchar name[],
unsigned port,
void * param
) {
ASSERT(lookupProc);
ASSERT(name);
PerfAddCounter(kAsyncPerfNameLookupAttemptsCurr, 1);
PerfAddCounter(kAsyncPerfNameLookupAttemptsTotal, 1);
// Get name/port
char ansiName[kMaxLookupName];
StrToAnsi(ansiName, name, arrsize(ansiName));
if (char * portStr = StrChr(ansiName, ':')) {
if (unsigned newPort = StrToUnsigned(portStr + 1, nil, 10))
port = newPort;
*portStr = 0;
}
// Initialize lookup
Lookup * lookup = NEW(Lookup);
lookup->lookupProc = lookupProc;
lookup->port = port;
lookup->param = param;
StrCopy(lookup->name, name, arrsize(lookup->name));
s_critsect.Enter();
{
// Start the lookup thread if it wasn't started already
StartLookupThread();
s_lookupList.Link(lookup);
// get cancel id; we can avoid checking for zero by always using an odd number
ASSERT(s_nextLookupCancelId & 1);
s_nextLookupCancelId += 2;
*cancelId = lookup->cancelId = (AsyncCancelId) s_nextLookupCancelId;
// Perform async lookup
lookup->cancelHandle = WSAAsyncGetHostByName(
s_lookupWindow,
WM_LOOKUP_FOUND_HOST,
ansiName,
&lookup->buffer[0],
sizeof(lookup->buffer)
);
if (!lookup->cancelHandle) {
PostMessage(s_lookupWindow, WM_LOOKUP_FOUND_HOST, nil, (unsigned) -1);
}
}
s_critsect.Leave();
}
//===========================================================================
void AsyncAddressLookupAddr (
AsyncCancelId * cancelId, // out
FAsyncLookupProc lookupProc,
const NetAddress & address,
void * param
) {
ASSERT(lookupProc);
PerfAddCounter(kAsyncPerfNameLookupAttemptsCurr, 1);
PerfAddCounter(kAsyncPerfNameLookupAttemptsTotal, 1);
// Initialize lookup
Lookup * lookup = NEW(Lookup);
lookup->lookupProc = lookupProc;
lookup->port = 1;
lookup->param = param;
NetAddressToString(
address,
lookup->name,
arrsize(lookup->name),
kNetAddressFormatNodeNumber
);
s_critsect.Enter();
{
// Start the lookup thread if it wasn't started already
StartLookupThread();
s_lookupList.Link(lookup);
// get cancel id; we can avoid checking for zero by always using an odd number
ASSERT(s_nextLookupCancelId & 1);
s_nextLookupCancelId += 2;
*cancelId = lookup->cancelId = (AsyncCancelId) s_nextLookupCancelId;
// Perform async lookup
u_long addr = ((const sockaddr_in *) &address)->sin_addr.S_un.S_addr;
lookup->cancelHandle = WSAAsyncGetHostByAddr(
s_lookupWindow,
WM_LOOKUP_FOUND_HOST,
(const char *) &addr,
sizeof(addr),
AF_INET,
&lookup->buffer[0],
sizeof(lookup->buffer)
);
if (!lookup->cancelHandle) {
PostMessage(s_lookupWindow, WM_LOOKUP_FOUND_HOST, nil, (unsigned) -1);
}
}
s_critsect.Leave();
}
//===========================================================================
void AsyncAddressLookupCancel (
FAsyncLookupProc lookupProc,
AsyncCancelId cancelId // nil = cancel all with specified lookupProc
) {
s_critsect.Enter();
for (Lookup * lookup = s_lookupList.Head(); lookup; lookup = s_lookupList.Next(lookup)) {
if (lookup->lookupProc && (lookup->lookupProc != lookupProc))
continue;
if (cancelId && (lookup->cancelId != cancelId))
continue;
if (!lookup->cancelHandle)
continue;
// cancel this request
WSACancelAsyncRequest(lookup->cancelHandle);
lookup->cancelHandle = nil;
// initiate user callback
PostMessage(s_lookupWindow, WM_LOOKUP_FOUND_HOST, nil, (unsigned) -1);
}
s_critsect.Leave();
}

View File

@ -1,261 +1,261 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
/*****************************************************************************
*
* $/Plasma20/Sources/Plasma/NucleusLib/pnAsyncCoreExe/Private/Win32/pnAceW32Thread.cpp
*
***/
#include "../../Pch.h"
#pragma hdrstop
/*****************************************************************************
*
* Private
*
***/
struct AsyncThreadTaskList : AtomicRef {
ENetError error;
AsyncThreadTaskList ();
~AsyncThreadTaskList ();
};
struct ThreadTask {
AsyncThreadTaskList * taskList;
FAsyncThreadTask callback;
void * param;
wchar debugStr[256];
};
static HANDLE s_taskPort;
/*****************************************************************************
*
* AsyncThreadTaskList
*
***/
//===========================================================================
AsyncThreadTaskList::AsyncThreadTaskList ()
: error(kNetSuccess)
{
PerfAddCounter(kAsyncPerfThreadTaskListCount, 1);
}
//============================================================================
AsyncThreadTaskList::~AsyncThreadTaskList () {
PerfSubCounter(kAsyncPerfThreadTaskListCount, 1);
}
/*****************************************************************************
*
* Local functions
*
***/
/****************************************************************************
*
* ThreadTaskProc
*
***/
//===========================================================================
static unsigned THREADCALL ThreadTaskProc (AsyncThread * thread) {
PerfAddCounter(kAsyncPerfThreadTaskThreadsActive, 1);
for (;;) {
long desired = AsyncPerfGetCounter(kAsyncPerfThreadTaskThreadsDesired);
if (AsyncPerfGetCounter(kAsyncPerfThreadTaskThreadsRunning) > desired) {
long runningCount = PerfSubCounter(kAsyncPerfThreadTaskThreadsRunning, 1) - 1;
if (runningCount >= desired) {
if (runningCount > desired)
PostQueuedCompletionStatus(s_taskPort, 0, 0, 0);
break;
}
PerfAddCounter(kAsyncPerfThreadTaskThreadsRunning, 1);
}
// Get the next work item
DWORD bytes;
ThreadTask * task;
LPOVERLAPPED op;
PerfSubCounter(kAsyncPerfThreadTaskThreadsActive, 1);
(void) GetQueuedCompletionStatus(
s_taskPort,
&bytes,
#ifdef _WIN64
(PULONG_PTR) &task,
#else
(LPDWORD) &task,
#endif
&op,
INFINITE
);
PerfAddCounter(kAsyncPerfThreadTaskThreadsActive, 1);
if (task) {
#ifdef SERVER
void * check = CrashAddDeadlockCheck(thread->handle, task->debugStr);
#endif
task->callback(task->param, task->taskList->error);
#ifdef SERVER
CrashRemoveDeadlockCheck(check);
#endif
task->taskList->DecRef("task");
DEL(task);
}
}
PerfSubCounter(kAsyncPerfThreadTaskThreadsActive, 1);
return 0;
}
//===========================================================================
static unsigned THREADCALL FirstThreadTaskProc (AsyncThread * param) {
while (AsyncPerfGetCounter(kAsyncPerfThreadTaskThreadsRunning) < AsyncPerfGetCounter(kAsyncPerfThreadTaskThreadsDesired)) {
PerfAddCounter(kAsyncPerfThreadTaskThreadsRunning, 1);
AsyncThreadCreate(ThreadTaskProc, nil, L"AsyncThreadTaskList");
}
return ThreadTaskProc(param);
}
/*****************************************************************************
*
* Module functions
*
***/
/*****************************************************************************
*
* Exports
*
***/
//============================================================================
void AsyncThreadTaskInitialize (unsigned threads) {
// Create completion port
s_taskPort = CreateIoCompletionPort(INVALID_HANDLE_VALUE, 0, 0, 0);
ASSERT(s_taskPort);
// Create threads
AsyncThreadTaskSetThreadCount(threads);
}
//============================================================================
void AsyncThreadTaskDestroy () {
ASSERT(!AsyncPerfGetCounter(kAsyncPerfThreadTaskListCount));
if (s_taskPort) {
PerfSetCounter(kAsyncPerfThreadTaskThreadsDesired, 0);
PostQueuedCompletionStatus(s_taskPort, 0, 0, 0);
// Wait until all threads have exited
while (AsyncPerfGetCounter(kAsyncPerfThreadTaskThreadsActive))
AsyncSleep(10);
while (AsyncPerfGetCounter(kAsyncPerfThreadTaskThreadsRunning))
AsyncSleep(10);
// Cleanup completion port
CloseHandle(s_taskPort);
s_taskPort = nil;
}
}
//===========================================================================
unsigned AsyncThreadTaskGetThreadCount () {
return AsyncPerfGetCounter(kAsyncPerfThreadTaskThreadsDesired);
}
//===========================================================================
void AsyncThreadTaskSetThreadCount (unsigned threads) {
ASSERT(threads >= kThreadTaskMinThreads);
ASSERT(threads <= kThreadTaskMaxThreads);
if (AsyncPerfGetCounter(kAsyncPerfThreadTaskThreadsDesired) == (long) threads)
return;
PerfSetCounter(kAsyncPerfThreadTaskThreadsDesired, (long) threads);
if (AsyncPerfGetCounter(kAsyncPerfThreadTaskThreadsRunning) < AsyncPerfGetCounter(kAsyncPerfThreadTaskThreadsDesired)) {
PerfAddCounter(kAsyncPerfThreadTaskThreadsRunning, 1);
AsyncThreadCreate(FirstThreadTaskProc, nil, L"ThreadTaskList");
}
else {
PostQueuedCompletionStatus(s_taskPort, 0, 0, 0);
}
}
//===========================================================================
AsyncThreadTaskList * AsyncThreadTaskListCreate () {
ASSERT(s_taskPort);
AsyncThreadTaskList * taskList = NEW(AsyncThreadTaskList);
taskList->IncRef("TaskList");
return taskList;
}
//===========================================================================
void AsyncThreadTaskListDestroy (
AsyncThreadTaskList * taskList,
ENetError error
) {
ASSERT(taskList);
ASSERT(error);
ASSERT(!taskList->error);
taskList->error = error;
taskList->DecRef(); // REF:TaskList
}
//===========================================================================
void AsyncThreadTaskAdd (
AsyncThreadTaskList * taskList,
FAsyncThreadTask callback,
void * param,
const wchar debugStr[],
EThreadTaskPriority priority /* = kThreadTaskPriorityNormal */
) {
ASSERT(s_taskPort);
ASSERT(taskList);
ASSERT(callback);
ASSERT(priority == kThreadTaskPriorityNormal);
// Allocate a new task record
ThreadTask * task = NEW(ThreadTask);
task->taskList = taskList;
task->callback = callback;
task->param = param;
StrCopy(task->debugStr, debugStr, arrsize(task->debugStr)); // this will be sent with the deadlock checker email if this thread exceeds time set in plServer.ini
taskList->IncRef("Task");
PostQueuedCompletionStatus(s_taskPort, 0, (DWORD) task, NULL);
}
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
/*****************************************************************************
*
* $/Plasma20/Sources/Plasma/NucleusLib/pnAsyncCoreExe/Private/Win32/pnAceW32Thread.cpp
*
***/
#include "../../Pch.h"
#pragma hdrstop
/*****************************************************************************
*
* Private
*
***/
struct AsyncThreadTaskList : AtomicRef {
ENetError error;
AsyncThreadTaskList ();
~AsyncThreadTaskList ();
};
struct ThreadTask {
AsyncThreadTaskList * taskList;
FAsyncThreadTask callback;
void * param;
wchar debugStr[256];
};
static HANDLE s_taskPort;
/*****************************************************************************
*
* AsyncThreadTaskList
*
***/
//===========================================================================
AsyncThreadTaskList::AsyncThreadTaskList ()
: error(kNetSuccess)
{
PerfAddCounter(kAsyncPerfThreadTaskListCount, 1);
}
//============================================================================
AsyncThreadTaskList::~AsyncThreadTaskList () {
PerfSubCounter(kAsyncPerfThreadTaskListCount, 1);
}
/*****************************************************************************
*
* Local functions
*
***/
/****************************************************************************
*
* ThreadTaskProc
*
***/
//===========================================================================
static unsigned THREADCALL ThreadTaskProc (AsyncThread * thread) {
PerfAddCounter(kAsyncPerfThreadTaskThreadsActive, 1);
for (;;) {
long desired = AsyncPerfGetCounter(kAsyncPerfThreadTaskThreadsDesired);
if (AsyncPerfGetCounter(kAsyncPerfThreadTaskThreadsRunning) > desired) {
long runningCount = PerfSubCounter(kAsyncPerfThreadTaskThreadsRunning, 1) - 1;
if (runningCount >= desired) {
if (runningCount > desired)
PostQueuedCompletionStatus(s_taskPort, 0, 0, 0);
break;
}
PerfAddCounter(kAsyncPerfThreadTaskThreadsRunning, 1);
}
// Get the next work item
DWORD bytes;
ThreadTask * task;
LPOVERLAPPED op;
PerfSubCounter(kAsyncPerfThreadTaskThreadsActive, 1);
(void) GetQueuedCompletionStatus(
s_taskPort,
&bytes,
#ifdef _WIN64
(PULONG_PTR) &task,
#else
(LPDWORD) &task,
#endif
&op,
INFINITE
);
PerfAddCounter(kAsyncPerfThreadTaskThreadsActive, 1);
if (task) {
#ifdef SERVER
void * check = CrashAddDeadlockCheck(thread->handle, task->debugStr);
#endif
task->callback(task->param, task->taskList->error);
#ifdef SERVER
CrashRemoveDeadlockCheck(check);
#endif
task->taskList->DecRef("task");
DEL(task);
}
}
PerfSubCounter(kAsyncPerfThreadTaskThreadsActive, 1);
return 0;
}
//===========================================================================
static unsigned THREADCALL FirstThreadTaskProc (AsyncThread * param) {
while (AsyncPerfGetCounter(kAsyncPerfThreadTaskThreadsRunning) < AsyncPerfGetCounter(kAsyncPerfThreadTaskThreadsDesired)) {
PerfAddCounter(kAsyncPerfThreadTaskThreadsRunning, 1);
AsyncThreadCreate(ThreadTaskProc, nil, L"AsyncThreadTaskList");
}
return ThreadTaskProc(param);
}
/*****************************************************************************
*
* Module functions
*
***/
/*****************************************************************************
*
* Exports
*
***/
//============================================================================
void AsyncThreadTaskInitialize (unsigned threads) {
// Create completion port
s_taskPort = CreateIoCompletionPort(INVALID_HANDLE_VALUE, 0, 0, 0);
ASSERT(s_taskPort);
// Create threads
AsyncThreadTaskSetThreadCount(threads);
}
//============================================================================
void AsyncThreadTaskDestroy () {
ASSERT(!AsyncPerfGetCounter(kAsyncPerfThreadTaskListCount));
if (s_taskPort) {
PerfSetCounter(kAsyncPerfThreadTaskThreadsDesired, 0);
PostQueuedCompletionStatus(s_taskPort, 0, 0, 0);
// Wait until all threads have exited
while (AsyncPerfGetCounter(kAsyncPerfThreadTaskThreadsActive))
AsyncSleep(10);
while (AsyncPerfGetCounter(kAsyncPerfThreadTaskThreadsRunning))
AsyncSleep(10);
// Cleanup completion port
CloseHandle(s_taskPort);
s_taskPort = nil;
}
}
//===========================================================================
unsigned AsyncThreadTaskGetThreadCount () {
return AsyncPerfGetCounter(kAsyncPerfThreadTaskThreadsDesired);
}
//===========================================================================
void AsyncThreadTaskSetThreadCount (unsigned threads) {
ASSERT(threads >= kThreadTaskMinThreads);
ASSERT(threads <= kThreadTaskMaxThreads);
if (AsyncPerfGetCounter(kAsyncPerfThreadTaskThreadsDesired) == (long) threads)
return;
PerfSetCounter(kAsyncPerfThreadTaskThreadsDesired, (long) threads);
if (AsyncPerfGetCounter(kAsyncPerfThreadTaskThreadsRunning) < AsyncPerfGetCounter(kAsyncPerfThreadTaskThreadsDesired)) {
PerfAddCounter(kAsyncPerfThreadTaskThreadsRunning, 1);
AsyncThreadCreate(FirstThreadTaskProc, nil, L"ThreadTaskList");
}
else {
PostQueuedCompletionStatus(s_taskPort, 0, 0, 0);
}
}
//===========================================================================
AsyncThreadTaskList * AsyncThreadTaskListCreate () {
ASSERT(s_taskPort);
AsyncThreadTaskList * taskList = NEW(AsyncThreadTaskList);
taskList->IncRef("TaskList");
return taskList;
}
//===========================================================================
void AsyncThreadTaskListDestroy (
AsyncThreadTaskList * taskList,
ENetError error
) {
ASSERT(taskList);
ASSERT(error);
ASSERT(!taskList->error);
taskList->error = error;
taskList->DecRef(); // REF:TaskList
}
//===========================================================================
void AsyncThreadTaskAdd (
AsyncThreadTaskList * taskList,
FAsyncThreadTask callback,
void * param,
const wchar debugStr[],
EThreadTaskPriority priority /* = kThreadTaskPriorityNormal */
) {
ASSERT(s_taskPort);
ASSERT(taskList);
ASSERT(callback);
ASSERT(priority == kThreadTaskPriorityNormal);
// Allocate a new task record
ThreadTask * task = NEW(ThreadTask);
task->taskList = taskList;
task->callback = callback;
task->param = param;
StrCopy(task->debugStr, debugStr, arrsize(task->debugStr)); // this will be sent with the deadlock checker email if this thread exceeds time set in plServer.ini
taskList->IncRef("Task");
PostQueuedCompletionStatus(s_taskPort, 0, (DWORD) task, NULL);
}

View File

@ -1,264 +1,264 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
/*****************************************************************************
*
* $/Plasma20/Sources/Plasma/NucleusLib/pnAsyncCoreExe/Private/pnAceInt.h
*
***/
#ifdef PLASMA20_SOURCES_PLASMA_NUCLEUSLIB_PNASYNCCOREEXE_PRIVATE_PNACEINT_H
#error "Header $/Plasma20/Sources/Plasma/NucleusLib/pnAsyncCoreExe/Private/pnAceInt.h included more than once"
#endif
#define PLASMA20_SOURCES_PLASMA_NUCLEUSLIB_PNASYNCCOREEXE_PRIVATE_PNACEINT_H
/*****************************************************************************
*
* Core.cpp
*
***/
// Performance counter functions
long PerfAddCounter (unsigned id, unsigned n);
long PerfSubCounter (unsigned id, unsigned n);
long PerfSetCounter (unsigned id, unsigned n);
/*****************************************************************************
*
* Dns.cpp
*
***/
void DnsDestroy (unsigned exitThreadWaitMs);
/*****************************************************************************
*
* Thread.cpp
*
***/
void ThreadDestroy (unsigned exitThreadWaitMs);
/*****************************************************************************
*
* Timer.cpp
*
***/
void TimerDestroy (unsigned exitThreadWaitMs);
/****************************************************************************
*
* Async API function types
*
***/
// Core
typedef void (* FInitialize) ();
typedef void (* FDestroy) (unsigned exitThreadWaitMs);
typedef void (* FSignalShutdown) ();
typedef void (* FWaitForShutdown) ();
typedef void (* FSleep) (unsigned sleepMs);
// Files
typedef AsyncFile (* FAsyncFileOpen) (
const wchar fullPath[],
FAsyncNotifyFileProc notifyProc,
EFileError * error,
unsigned desiredAccess,
unsigned openMode,
unsigned shareModeFlags,
void * userState,
qword * fileSize,
qword * fileLastWriteTime
);
typedef void (* FAsyncFileClose) (
AsyncFile file,
qword truncateSize
);
typedef void (* FAsyncFileSetLastWriteTime) (
AsyncFile file,
qword lastWriteTime
);
typedef qword (* FAsyncFileGetLastWriteTime) (
const wchar fileName[]
);
typedef AsyncId (* FAsyncFileFlushBuffers) (
AsyncFile file,
qword truncateSize,
bool notify,
void * param
);
typedef AsyncId (* FAsyncFileRead) (
AsyncFile file,
qword offset,
void * buffer,
unsigned bytes,
unsigned flags,
void * param
);
typedef AsyncId (* FAsyncFileWrite) (
AsyncFile file,
qword offset,
const void * buffer,
unsigned bytes,
unsigned flags,
void * param
);
typedef AsyncId (* FAsyncFileCreateSequence) (
AsyncFile file,
bool notify,
void * param
);
typedef bool (* FAsyncFileSeek) (
AsyncFile file,
qword distance,
EFileSeekFrom from
);
typedef bool (* FAsyncFileWaitId) (
AsyncFile file,
AsyncId asyncId,
unsigned timeoutMs
);
// Sockets
typedef void (* FAsyncSocketConnect) (
AsyncCancelId * cancelId,
const NetAddress & netAddr,
FAsyncNotifySocketProc notifyProc,
void * param,
const void * sendData,
unsigned sendBytes,
unsigned connectMs,
unsigned localPort
);
typedef void (* FAsyncSocketConnectCancel) (
FAsyncNotifySocketProc notifyProc,
AsyncCancelId cancelId
);
typedef void (* FAsyncSocketDisconnect) (
AsyncSocket sock,
bool hardClose
);
typedef void (* FAsyncSocketDelete) (AsyncSocket sock);
typedef bool (* FAsyncSocketSend) (
AsyncSocket sock,
const void * data,
unsigned bytes
);
typedef bool (* FAsyncSocketWrite) (
AsyncSocket sock,
const void * buffer,
unsigned bytes,
void * param
);
typedef void (* FAsyncSocketSetNotifyProc) (
AsyncSocket sock,
FAsyncNotifySocketProc notifyProc
);
typedef void (* FAsyncSocketSetBacklogAlloc) (
AsyncSocket sock,
unsigned bufferSize
);
typedef unsigned (* FAsyncSocketStartListening) (
const NetAddress & listenAddr,
FAsyncNotifySocketProc notifyProc
);
typedef void (* FAsyncSocketStopListening) (
const NetAddress & listenAddr,
FAsyncNotifySocketProc notifyProc
);
typedef void (* FAsyncSocketEnableNagling) (
AsyncSocket conn,
bool enable
);
/****************************************************************************
*
* I/O API
*
***/
struct AsyncApi {
// Init
FInitialize initialize;
FDestroy destroy;
FSignalShutdown signalShutdown;
FWaitForShutdown waitForShutdown;
FSleep sleep;
// Files
FAsyncFileOpen fileOpen;
FAsyncFileClose fileClose;
FAsyncFileRead fileRead;
FAsyncFileWrite fileWrite;
FAsyncFileFlushBuffers fileFlushBuffers;
FAsyncFileSetLastWriteTime fileSetLastWriteTime;
FAsyncFileGetLastWriteTime fileGetLastWriteTime;
FAsyncFileCreateSequence fileCreateSequence;
FAsyncFileSeek fileSeek;
// Sockets
FAsyncSocketConnect socketConnect;
FAsyncSocketConnectCancel socketConnectCancel;
FAsyncSocketDisconnect socketDisconnect;
FAsyncSocketDelete socketDelete;
FAsyncSocketSend socketSend;
FAsyncSocketWrite socketWrite;
FAsyncSocketSetNotifyProc socketSetNotifyProc;
FAsyncSocketSetBacklogAlloc socketSetBacklogAlloc;
FAsyncSocketStartListening socketStartListening;
FAsyncSocketStopListening socketStopListening;
FAsyncSocketEnableNagling socketEnableNagling;
};
extern AsyncApi g_api;
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
/*****************************************************************************
*
* $/Plasma20/Sources/Plasma/NucleusLib/pnAsyncCoreExe/Private/pnAceInt.h
*
***/
#ifdef PLASMA20_SOURCES_PLASMA_NUCLEUSLIB_PNASYNCCOREEXE_PRIVATE_PNACEINT_H
#error "Header $/Plasma20/Sources/Plasma/NucleusLib/pnAsyncCoreExe/Private/pnAceInt.h included more than once"
#endif
#define PLASMA20_SOURCES_PLASMA_NUCLEUSLIB_PNASYNCCOREEXE_PRIVATE_PNACEINT_H
/*****************************************************************************
*
* Core.cpp
*
***/
// Performance counter functions
long PerfAddCounter (unsigned id, unsigned n);
long PerfSubCounter (unsigned id, unsigned n);
long PerfSetCounter (unsigned id, unsigned n);
/*****************************************************************************
*
* Dns.cpp
*
***/
void DnsDestroy (unsigned exitThreadWaitMs);
/*****************************************************************************
*
* Thread.cpp
*
***/
void ThreadDestroy (unsigned exitThreadWaitMs);
/*****************************************************************************
*
* Timer.cpp
*
***/
void TimerDestroy (unsigned exitThreadWaitMs);
/****************************************************************************
*
* Async API function types
*
***/
// Core
typedef void (* FInitialize) ();
typedef void (* FDestroy) (unsigned exitThreadWaitMs);
typedef void (* FSignalShutdown) ();
typedef void (* FWaitForShutdown) ();
typedef void (* FSleep) (unsigned sleepMs);
// Files
typedef AsyncFile (* FAsyncFileOpen) (
const wchar fullPath[],
FAsyncNotifyFileProc notifyProc,
EFileError * error,
unsigned desiredAccess,
unsigned openMode,
unsigned shareModeFlags,
void * userState,
qword * fileSize,
qword * fileLastWriteTime
);
typedef void (* FAsyncFileClose) (
AsyncFile file,
qword truncateSize
);
typedef void (* FAsyncFileSetLastWriteTime) (
AsyncFile file,
qword lastWriteTime
);
typedef qword (* FAsyncFileGetLastWriteTime) (
const wchar fileName[]
);
typedef AsyncId (* FAsyncFileFlushBuffers) (
AsyncFile file,
qword truncateSize,
bool notify,
void * param
);
typedef AsyncId (* FAsyncFileRead) (
AsyncFile file,
qword offset,
void * buffer,
unsigned bytes,
unsigned flags,
void * param
);
typedef AsyncId (* FAsyncFileWrite) (
AsyncFile file,
qword offset,
const void * buffer,
unsigned bytes,
unsigned flags,
void * param
);
typedef AsyncId (* FAsyncFileCreateSequence) (
AsyncFile file,
bool notify,
void * param
);
typedef bool (* FAsyncFileSeek) (
AsyncFile file,
qword distance,
EFileSeekFrom from
);
typedef bool (* FAsyncFileWaitId) (
AsyncFile file,
AsyncId asyncId,
unsigned timeoutMs
);
// Sockets
typedef void (* FAsyncSocketConnect) (
AsyncCancelId * cancelId,
const NetAddress & netAddr,
FAsyncNotifySocketProc notifyProc,
void * param,
const void * sendData,
unsigned sendBytes,
unsigned connectMs,
unsigned localPort
);
typedef void (* FAsyncSocketConnectCancel) (
FAsyncNotifySocketProc notifyProc,
AsyncCancelId cancelId
);
typedef void (* FAsyncSocketDisconnect) (
AsyncSocket sock,
bool hardClose
);
typedef void (* FAsyncSocketDelete) (AsyncSocket sock);
typedef bool (* FAsyncSocketSend) (
AsyncSocket sock,
const void * data,
unsigned bytes
);
typedef bool (* FAsyncSocketWrite) (
AsyncSocket sock,
const void * buffer,
unsigned bytes,
void * param
);
typedef void (* FAsyncSocketSetNotifyProc) (
AsyncSocket sock,
FAsyncNotifySocketProc notifyProc
);
typedef void (* FAsyncSocketSetBacklogAlloc) (
AsyncSocket sock,
unsigned bufferSize
);
typedef unsigned (* FAsyncSocketStartListening) (
const NetAddress & listenAddr,
FAsyncNotifySocketProc notifyProc
);
typedef void (* FAsyncSocketStopListening) (
const NetAddress & listenAddr,
FAsyncNotifySocketProc notifyProc
);
typedef void (* FAsyncSocketEnableNagling) (
AsyncSocket conn,
bool enable
);
/****************************************************************************
*
* I/O API
*
***/
struct AsyncApi {
// Init
FInitialize initialize;
FDestroy destroy;
FSignalShutdown signalShutdown;
FWaitForShutdown waitForShutdown;
FSleep sleep;
// Files
FAsyncFileOpen fileOpen;
FAsyncFileClose fileClose;
FAsyncFileRead fileRead;
FAsyncFileWrite fileWrite;
FAsyncFileFlushBuffers fileFlushBuffers;
FAsyncFileSetLastWriteTime fileSetLastWriteTime;
FAsyncFileGetLastWriteTime fileGetLastWriteTime;
FAsyncFileCreateSequence fileCreateSequence;
FAsyncFileSeek fileSeek;
// Sockets
FAsyncSocketConnect socketConnect;
FAsyncSocketConnectCancel socketConnectCancel;
FAsyncSocketDisconnect socketDisconnect;
FAsyncSocketDelete socketDelete;
FAsyncSocketSend socketSend;
FAsyncSocketWrite socketWrite;
FAsyncSocketSetNotifyProc socketSetNotifyProc;
FAsyncSocketSetBacklogAlloc socketSetBacklogAlloc;
FAsyncSocketStartListening socketStartListening;
FAsyncSocketStopListening socketStopListening;
FAsyncSocketEnableNagling socketEnableNagling;
};
extern AsyncApi g_api;