Revert to legacy Windows behavior since Windows 10 allows CreateThread in Universal apps

This commit is contained in:
Cameron Gutman 2015-06-30 23:24:49 -07:00
parent 7814cb3fae
commit 25612824ca
8 changed files with 64 additions and 141 deletions

View File

@ -10,7 +10,6 @@ struct sockaddr_storage RemoteAddr;
SOCKADDR_LEN RemoteAddrLen;
int ServerMajorVersion;
STREAM_CONFIGURATION StreamConfig;
PLATFORM_CALLBACKS PlatformCallbacks;
CONNECTION_LISTENER_CALLBACKS ListenerCallbacks;
DECODER_RENDERER_CALLBACKS VideoCallbacks;
AUDIO_RENDERER_CALLBACKS AudioCallbacks;
@ -119,11 +118,6 @@ static void ClInternalConnectionTerminated(long errorCode)
originalTerminationCallback(errorCode);
}
void LiCompleteThreadStart(void)
{
PltRunThreadProc();
}
static int resolveHostName(const char *host)
{
struct addrinfo hints, *res;
@ -153,7 +147,7 @@ static int resolveHostName(const char *host)
/* Starts the connection to the streaming machine */
int LiStartConnection(const char* host, PSTREAM_CONFIGURATION streamConfig, PCONNECTION_LISTENER_CALLBACKS clCallbacks,
PDECODER_RENDERER_CALLBACKS drCallbacks, PAUDIO_RENDERER_CALLBACKS arCallbacks, PPLATFORM_CALLBACKS plCallbacks,
PDECODER_RENDERER_CALLBACKS drCallbacks, PAUDIO_RENDERER_CALLBACKS arCallbacks,
void* renderContext, int drFlags, int _serverMajorVersion) {
int err;
@ -161,8 +155,7 @@ int LiStartConnection(const char* host, PSTREAM_CONFIGURATION streamConfig, PCON
memcpy(&StreamConfig, streamConfig, sizeof(StreamConfig));
// Replace missing callbacks with placeholders
fixupMissingCallbacks(&drCallbacks, &arCallbacks, &clCallbacks, &plCallbacks);
memcpy(&PlatformCallbacks, plCallbacks, sizeof(PlatformCallbacks));
fixupMissingCallbacks(&drCallbacks, &arCallbacks, &clCallbacks);
memcpy(&VideoCallbacks, drCallbacks, sizeof(VideoCallbacks));
memcpy(&AudioCallbacks, arCallbacks, sizeof(AudioCallbacks));

View File

@ -38,16 +38,8 @@ static CONNECTION_LISTENER_CALLBACKS fakeClCallbacks = {
.displayTransientMessage = fakeClDisplayTransientMessage,
};
static void fakePlThreadStart(void) {}
static void fakePlDebugPrint(char* string) {}
static PLATFORM_CALLBACKS fakePlCallbacks = {
.threadStart = fakePlThreadStart,
.debugPrint = fakePlDebugPrint,
};
void fixupMissingCallbacks(PDECODER_RENDERER_CALLBACKS *drCallbacks, PAUDIO_RENDERER_CALLBACKS *arCallbacks,
PCONNECTION_LISTENER_CALLBACKS *clCallbacks, PPLATFORM_CALLBACKS *plCallbacks)
PCONNECTION_LISTENER_CALLBACKS *clCallbacks)
{
if (*drCallbacks == NULL) {
*drCallbacks = &fakeDrCallbacks;
@ -105,16 +97,4 @@ void fixupMissingCallbacks(PDECODER_RENDERER_CALLBACKS *drCallbacks, PAUDIO_REND
(*clCallbacks)->displayTransientMessage = fakeClDisplayTransientMessage;
}
}
if (*plCallbacks == NULL) {
*plCallbacks = &fakePlCallbacks;
}
else {
if ((*plCallbacks)->threadStart == NULL) {
(*plCallbacks)->threadStart = fakePlThreadStart;
}
if ((*plCallbacks)->debugPrint == NULL) {
(*plCallbacks)->debugPrint = fakePlDebugPrint;
}
}
}

View File

@ -11,7 +11,6 @@ extern struct sockaddr_storage RemoteAddr;
extern SOCKADDR_LEN RemoteAddrLen;
extern int ServerMajorVersion;
extern STREAM_CONFIGURATION StreamConfig;
extern PLATFORM_CALLBACKS PlatformCallbacks;
extern CONNECTION_LISTENER_CALLBACKS ListenerCallbacks;
extern DECODER_RENDERER_CALLBACKS VideoCallbacks;
extern AUDIO_RENDERER_CALLBACKS AudioCallbacks;
@ -19,7 +18,7 @@ extern AUDIO_RENDERER_CALLBACKS AudioCallbacks;
int isBeforeSignedInt(int numA, int numB, int ambiguousCase);
void fixupMissingCallbacks(PDECODER_RENDERER_CALLBACKS *drCallbacks, PAUDIO_RENDERER_CALLBACKS *arCallbacks,
PCONNECTION_LISTENER_CALLBACKS *clCallbacks, PPLATFORM_CALLBACKS *plCallbacks);
PCONNECTION_LISTENER_CALLBACKS *clCallbacks);
char* getSdpPayloadForStreamConfig(int rtspClientVersion, int *length);

View File

@ -132,19 +132,6 @@ typedef struct _CONNECTION_LISTENER_CALLBACKS {
ConnListenerDisplayTransientMessage displayTransientMessage;
} CONNECTION_LISTENER_CALLBACKS, *PCONNECTION_LISTENER_CALLBACKS;
// This is a Windows-only callback used to indicate that the client
// should call LiCompleteThreadStart() from a new thread as soon as possible.
typedef void(*PlatformThreadStart)(void);
// This is a Windows-only callback used to display a debug message for
// developer use.
typedef void(*PlatformDebugPrint)(char* string);
typedef struct _PLATFORM_CALLBACKS {
PlatformThreadStart threadStart;
PlatformDebugPrint debugPrint;
} PLATFORM_CALLBACKS, *PPLATFORM_CALLBACKS;
// This function begins streaming.
//
// Callbacks are all optional. Pass NULL for individual callbacks within each struct or pass NULL for the entire struct
@ -153,8 +140,7 @@ typedef struct _PLATFORM_CALLBACKS {
// _serverMajorVersion is the major version number of the 'appversion' tag in the /serverinfo request
//
int LiStartConnection(const char* host, PSTREAM_CONFIGURATION streamConfig, PCONNECTION_LISTENER_CALLBACKS clCallbacks,
PDECODER_RENDERER_CALLBACKS drCallbacks, PAUDIO_RENDERER_CALLBACKS arCallbacks, PPLATFORM_CALLBACKS plCallbacks,
void* renderContext, int drFlags, int _serverMajorVersion);
PDECODER_RENDERER_CALLBACKS drCallbacks, PAUDIO_RENDERER_CALLBACKS arCallbacks, void* renderContext, int drFlags, int _serverMajorVersion);
// This function stops streaming.
void LiStopConnection(void);
@ -163,11 +149,6 @@ void LiStopConnection(void);
// from the integer passed to the ConnListenerStageXXX callbacks
const char* LiGetStageName(int stage);
#ifdef _WIN32
/* Call in the context of a new thread */
void LiCompleteThreadStart(void);
#endif
// This function queues a mouse move event to be sent to the remote server.
int LiSendMouseMoveEvent(short deltaX, short deltaY);

View File

@ -1,17 +1,26 @@
#include "PlatformThreads.h"
#include "Platform.h"
#if defined(LC_WINDOWS)
WCHAR DbgBuf[512];
#endif
int initializePlatformSockets(void);
void cleanupPlatformSockets(void);
#if defined(LC_WINDOWS_PHONE) || defined(LC_WINDOWS)
CHAR DbgBuf[512];
#endif
#if defined(LC_WINDOWS)
PLT_MUTEX thread_list_lock;
PLT_THREAD *thread_head;
#if defined(LC_WINDOWS) || defined(LC_WINDOWS_PHONE)
static PLT_MUTEX thread_list_lock;
static PLT_THREAD *pending_thread_head;
static PLT_THREAD *thread_head;
DWORD WINAPI ThreadProc(LPVOID lpParameter) {
struct thread_context *ctx = (struct thread_context *)lpParameter;
ctx->entry(ctx->context);
free(ctx);
return 0;
}
#else
void* ThreadProc(void* context) {
struct thread_context *ctx = (struct thread_context *)context;
@ -25,7 +34,7 @@ void* ThreadProc(void* context) {
#endif
void PltSleepMs(int ms) {
#if defined(LC_WINDOWS) || defined (LC_WINDOWS_PHONE)
#if defined(LC_WINDOWS)
WaitForSingleObjectEx(GetCurrentThread(), ms, FALSE);
#else
useconds_t usecs = ms * 1000;
@ -34,7 +43,7 @@ void PltSleepMs(int ms) {
}
int PltCreateMutex(PLT_MUTEX *mutex) {
#if defined(LC_WINDOWS) || defined(LC_WINDOWS_PHONE)
#if defined(LC_WINDOWS)
*mutex = CreateMutexEx(NULL, NULL, 0, MUTEX_ALL_ACCESS);
if (!*mutex) {
return -1;
@ -46,7 +55,7 @@ int PltCreateMutex(PLT_MUTEX *mutex) {
}
void PltDeleteMutex(PLT_MUTEX *mutex) {
#if defined(LC_WINDOWS) || defined(LC_WINDOWS_PHONE)
#if defined(LC_WINDOWS)
CloseHandle(*mutex);
#else
pthread_mutex_destroy(mutex);
@ -54,7 +63,7 @@ void PltDeleteMutex(PLT_MUTEX *mutex) {
}
void PltLockMutex(PLT_MUTEX *mutex) {
#if defined(LC_WINDOWS) || defined(LC_WINDOWS_PHONE)
#if defined(LC_WINDOWS)
int err;
err = WaitForSingleObjectEx(*mutex, INFINITE, FALSE);
if (err != WAIT_OBJECT_0) {
@ -66,7 +75,7 @@ void PltLockMutex(PLT_MUTEX *mutex) {
}
void PltUnlockMutex(PLT_MUTEX *mutex) {
#if defined(LC_WINDOWS) || defined(LC_WINDOWS_PHONE)
#if defined(LC_WINDOWS)
ReleaseMutex(*mutex);
#else
pthread_mutex_unlock(mutex);
@ -74,16 +83,15 @@ void PltUnlockMutex(PLT_MUTEX *mutex) {
}
void PltJoinThread(PLT_THREAD *thread) {
#if defined(LC_WINDOWS) || defined(LC_WINDOWS_PHONE)
// Wait for the thread to leave our code
WaitForSingleObjectEx(thread->termCompleted, INFINITE, FALSE);
#if defined(LC_WINDOWS)
WaitForSingleObjectEx(thread->handle, INFINITE, FALSE);
#else
pthread_join(*thread, NULL);
#endif
}
void PltCloseThread(PLT_THREAD *thread) {
#if defined(LC_WINDOWS) || defined(LC_WINDOWS_PHONE)
#if defined(LC_WINDOWS)
PLT_THREAD *current_thread;
PltLockMutex(&thread_list_lock);
@ -114,13 +122,13 @@ void PltCloseThread(PLT_THREAD *thread) {
PltUnlockMutex(&thread_list_lock);
CloseHandle(thread->termRequested);
CloseHandle(thread->termCompleted);
CloseHandle(thread->handle);
#else
#endif
}
int PltIsThreadInterrupted(PLT_THREAD *thread) {
#if defined(LC_WINDOWS) || defined(LC_WINDOWS_PHONE)
#if defined(LC_WINDOWS)
return thread->cancelled;
#else
// The thread will die here if a cancellation was requested
@ -130,7 +138,7 @@ int PltIsThreadInterrupted(PLT_THREAD *thread) {
}
void PltInterruptThread(PLT_THREAD *thread) {
#if defined(LC_WINDOWS) || defined(LC_WINDOWS_PHONE)
#if defined(LC_WINDOWS)
thread->cancelled = 1;
SetEvent(thread->termRequested);
#else
@ -138,41 +146,6 @@ void PltInterruptThread(PLT_THREAD *thread) {
#endif
}
void PltRunThreadProc(void) {
#if defined(LC_WINDOWS) || defined(LC_WINDOWS_PHONE)
PLT_THREAD *thread;
// Grab the first entry from the pending list and move it
// to the active list
PltLockMutex(&thread_list_lock);
thread = pending_thread_head;
// If there's no pending thread, something is seriously wrong
LC_ASSERT(thread != NULL);
pending_thread_head = pending_thread_head->next;
thread->next = thread_head;
thread_head = thread;
PltUnlockMutex(&thread_list_lock);
// Set up final thread state before running
thread->tid = GetCurrentThreadId();
// Now we're going to invoke the thread proc
thread->ctx->entry(thread->ctx->context);
free(thread->ctx);
// Signal the event to indicate the thread has "terminated"
SetEvent(thread->termCompleted);
// PltCloseThread() frees this state
#else
// This code shouldn't be called on *NIX
LC_ASSERT(0);
#endif
}
int PltCreateThread(ThreadEntry entry, void* context, PLT_THREAD *thread) {
struct thread_context *ctx;
int err;
@ -185,7 +158,7 @@ int PltCreateThread(ThreadEntry entry, void* context, PLT_THREAD *thread) {
ctx->entry = entry;
ctx->context = context;
#if defined(LC_WINDOWS) || defined(LC_WINDOWS_PHONE)
#if defined(LC_WINDOWS)
{
thread->termRequested = CreateEventEx(NULL, NULL, CREATE_EVENT_MANUAL_RESET, EVENT_ALL_ACCESS);
if (thread->termRequested == NULL) {
@ -193,26 +166,27 @@ int PltCreateThread(ThreadEntry entry, void* context, PLT_THREAD *thread) {
return -1;
}
thread->termCompleted = CreateEventEx(NULL, NULL, CREATE_EVENT_MANUAL_RESET, EVENT_ALL_ACCESS);
if (thread->termCompleted == NULL) {
thread->cancelled = 0;
thread->handle = CreateThread(NULL, 0, ThreadProc, ctx, CREATE_SUSPENDED, &thread->tid);
if (thread->handle == NULL) {
CloseHandle(thread->termRequested);
free(ctx);
return -1;
}
else {
// Add this thread to the thread list
PltLockMutex(&thread_list_lock);
thread->next = thread_head;
thread_head = thread;
PltUnlockMutex(&thread_list_lock);
thread->cancelled = 0;
thread->ctx = ctx;
// Now the thread can run
ResumeThread(thread->handle);
// Queue on the pending threads list
PltLockMutex(&thread_list_lock);
thread->next = pending_thread_head;
pending_thread_head = thread;
PltUnlockMutex(&thread_list_lock);
err = 0;
}
// Make a callback to managed code to ask for a thread to grab this
PlatformCallbacks.threadStart();
err = 0;
}
#else
{
@ -227,7 +201,7 @@ int PltCreateThread(ThreadEntry entry, void* context, PLT_THREAD *thread) {
}
int PltCreateEvent(PLT_EVENT *event) {
#if defined(LC_WINDOWS) || defined(LC_WINDOWS_PHONE)
#if defined(LC_WINDOWS)
*event = CreateEventEx(NULL, NULL, CREATE_EVENT_MANUAL_RESET, EVENT_ALL_ACCESS);
if (!*event) {
return -1;
@ -243,7 +217,7 @@ int PltCreateEvent(PLT_EVENT *event) {
}
void PltCloseEvent(PLT_EVENT *event) {
#if defined(LC_WINDOWS) || defined(LC_WINDOWS_PHONE)
#if defined(LC_WINDOWS)
CloseHandle(*event);
#else
pthread_mutex_destroy(&event->mutex);
@ -252,7 +226,7 @@ void PltCloseEvent(PLT_EVENT *event) {
}
void PltSetEvent(PLT_EVENT *event) {
#if defined(LC_WINDOWS) || defined(LC_WINDOWS_PHONE)
#if defined(LC_WINDOWS)
SetEvent(*event);
#else
event->signalled = 1;
@ -261,7 +235,7 @@ void PltSetEvent(PLT_EVENT *event) {
}
void PltClearEvent(PLT_EVENT *event) {
#if defined(LC_WINDOWS) || defined(LC_WINDOWS_PHONE)
#if defined(LC_WINDOWS)
ResetEvent(*event);
#else
event->signalled = 0;
@ -269,7 +243,7 @@ void PltClearEvent(PLT_EVENT *event) {
}
int PltWaitForEvent(PLT_EVENT *event) {
#if defined(LC_WINDOWS) || defined(LC_WINDOWS_PHONE)
#if defined(LC_WINDOWS)
DWORD error;
PLT_THREAD *current_thread;
HANDLE objects[2];
@ -311,7 +285,7 @@ int PltWaitForEvent(PLT_EVENT *event) {
}
uint64_t PltGetMillis(void) {
#if defined(LC_WINDOWS) || defined(LC_WINDOWS_PHONE)
#if defined(LC_WINDOWS)
return GetTickCount64();
#else
struct timeval tv;
@ -330,7 +304,7 @@ int initializePlatform(void) {
return err;
}
#if defined(LC_WINDOWS) || defined(LC_WINDOWS_PHONE)
#if defined(LC_WINDOWS)
return PltCreateMutex(&thread_list_lock);
#else
return 0;
@ -340,8 +314,7 @@ int initializePlatform(void) {
void cleanupPlatform(void) {
cleanupPlatformSockets();
#if defined(LC_WINDOWS) || defined(LC_WINDOWS_PHONE)
LC_ASSERT(pending_thread_head == NULL);
#if defined(LC_WINDOWS)
LC_ASSERT(thread_head == NULL);
PltDeleteMutex(&thread_list_lock);

View File

@ -27,18 +27,17 @@
#include <stdio.h>
#include "Limelight.h"
#if defined(LC_WINDOWS_PHONE) || defined(LC_WINDOWS)
extern char DbgBuf[512];
extern PLATFORM_CALLBACKS PlatformCallbacks;
#if defined(LC_WINDOWS)
extern WCHAR DbgBuf[512];
#define Limelog(s, ...) \
sprintf(DbgBuf, s, ##__VA_ARGS__); \
PlatformCallbacks.debugPrint(DbgBuf)
swprintf(DbgBuf, sizeof(DbgBuf) / sizeof(WCHAR), L ## s, ##__VA_ARGS__); \
OutputDebugStringW(DbgBuf)
#else
#define Limelog(s, ...) \
fprintf(stderr, s, ##__VA_ARGS__)
#endif
#if defined(LC_WINDOWS_PHONE) || defined(LC_WINDOWS)
#if defined(LC_WINDOWS)
#include <crtdbg.h>
#define LC_ASSERT(x) __analysis_assume(x); \
_ASSERTE(x)

View File

@ -108,7 +108,7 @@ int enableNoDelay(SOCKET s) {
}
int initializePlatformSockets(void) {
#if defined(LC_WINDOWS) || defined(LC_WINDOWS_PHONE)
#if defined(LC_WINDOWS)
WSADATA data;
return WSAStartup(MAKEWORD(2, 0), &data);
#elif defined(LC_POSIX)
@ -129,7 +129,7 @@ int initializePlatformSockets(void) {
}
void cleanupPlatformSockets(void) {
#if defined(LC_WINDOWS) || defined(LC_WINDOWS_PHONE)
#if defined(LC_WINDOWS)
WSACleanup();
#else
#endif

View File

@ -10,14 +10,12 @@ struct thread_context {
void* context;
};
#if defined(LC_WINDOWS) || defined(LC_WINDOWS_PHONE)
#if defined(LC_WINDOWS)
typedef struct _PLT_THREAD {
HANDLE handle;
int cancelled;
DWORD tid;
HANDLE termRequested;
HANDLE termCompleted;
struct thread_context *ctx;
struct _PLT_THREAD *next;
} PLT_THREAD;