src/thread/stdcpp/SDL_syscond.cpp
author David Ludwig
Sat, 24 Nov 2012 11:17:23 -0500
changeset 8360 7f1bc00e59fc
parent 8357 8d788bb003f2
child 8484 7258989352eb
permissions -rw-r--r--
WinRT: added a functional threading backend using C++11 apis
dludwig@8356
     1
/*
dludwig@8356
     2
  Simple DirectMedia Layer
dludwig@8356
     3
  Copyright (C) 1997-2012 Sam Lantinga <slouken@libsdl.org>
dludwig@8356
     4
dludwig@8356
     5
  This software is provided 'as-is', without any express or implied
dludwig@8356
     6
  warranty.  In no event will the authors be held liable for any damages
dludwig@8356
     7
  arising from the use of this software.
dludwig@8356
     8
dludwig@8356
     9
  Permission is granted to anyone to use this software for any purpose,
dludwig@8356
    10
  including commercial applications, and to alter it and redistribute it
dludwig@8356
    11
  freely, subject to the following restrictions:
dludwig@8356
    12
dludwig@8356
    13
  1. The origin of this software must not be misrepresented; you must not
dludwig@8356
    14
     claim that you wrote the original software. If you use this software
dludwig@8356
    15
     in a product, an acknowledgment in the product documentation would be
dludwig@8356
    16
     appreciated but is not required.
dludwig@8356
    17
  2. Altered source versions must be plainly marked as such, and must not be
dludwig@8356
    18
     misrepresented as being the original software.
dludwig@8356
    19
  3. This notice may not be removed or altered from any source distribution.
dludwig@8356
    20
*/
dludwig@8356
    21
#include "SDL_config.h"
dludwig@8356
    22
dludwig@8360
    23
extern "C" {
dludwig@8360
    24
#include "SDL_thread.h"
dludwig@8360
    25
}
dludwig@8356
    26
dludwig@8360
    27
#include <chrono>
dludwig@8360
    28
#include <condition_variable>
dludwig@8360
    29
#include <exception>
dludwig@8360
    30
#include <ratio>
dludwig@8360
    31
dludwig@8360
    32
#include "SDL_sysmutex_c.h"
dludwig@8356
    33
dludwig@8356
    34
struct SDL_cond
dludwig@8356
    35
{
dludwig@8360
    36
    std::condition_variable_any cpp_cond;
dludwig@8356
    37
};
dludwig@8356
    38
dludwig@8356
    39
/* Create a condition variable */
dludwig@8357
    40
extern "C"
dludwig@8356
    41
SDL_cond *
dludwig@8356
    42
SDL_CreateCond(void)
dludwig@8356
    43
{
dludwig@8360
    44
    /* Allocate and initialize the condition variable */
dludwig@8360
    45
    try {
dludwig@8360
    46
        SDL_cond * cond = new SDL_cond;
dludwig@8360
    47
        return cond;
dludwig@8360
    48
    } catch (std::exception & ex) {
dludwig@8360
    49
        SDL_SetError("unable to create C++ condition variable: %s", ex.what());
dludwig@8360
    50
        return NULL;
dludwig@8360
    51
    } catch (...) {
dludwig@8360
    52
        SDL_SetError("unable to create C++ condition variable due to an unknown exception");
dludwig@8360
    53
        return NULL;
dludwig@8356
    54
    }
dludwig@8356
    55
}
dludwig@8356
    56
dludwig@8356
    57
/* Destroy a condition variable */
dludwig@8357
    58
extern "C"
dludwig@8356
    59
void
dludwig@8356
    60
SDL_DestroyCond(SDL_cond * cond)
dludwig@8356
    61
{
dludwig@8356
    62
    if (cond) {
dludwig@8360
    63
        try {
dludwig@8360
    64
            delete cond;
dludwig@8360
    65
        } catch (...) {
dludwig@8360
    66
            // catch any and all exceptions, just in case something happens
dludwig@8356
    67
        }
dludwig@8356
    68
    }
dludwig@8356
    69
}
dludwig@8356
    70
dludwig@8356
    71
/* Restart one of the threads that are waiting on the condition variable */
dludwig@8357
    72
extern "C"
dludwig@8356
    73
int
dludwig@8356
    74
SDL_CondSignal(SDL_cond * cond)
dludwig@8356
    75
{
dludwig@8356
    76
    if (!cond) {
dludwig@8356
    77
        SDL_SetError("Passed a NULL condition variable");
dludwig@8356
    78
        return -1;
dludwig@8356
    79
    }
dludwig@8356
    80
dludwig@8360
    81
    try {
dludwig@8360
    82
        cond->cpp_cond.notify_one();
dludwig@8360
    83
        return 0;
dludwig@8360
    84
    } catch (...) {
dludwig@8360
    85
        // catch any and all exceptions, just in case something happens
dludwig@8360
    86
        SDL_SetError("unable to signal C++ condition variable due to an unknown exception");
dludwig@8360
    87
        return -1;
dludwig@8356
    88
    }
dludwig@8356
    89
}
dludwig@8356
    90
dludwig@8356
    91
/* Restart all threads that are waiting on the condition variable */
dludwig@8357
    92
extern "C"
dludwig@8356
    93
int
dludwig@8356
    94
SDL_CondBroadcast(SDL_cond * cond)
dludwig@8356
    95
{
dludwig@8356
    96
    if (!cond) {
dludwig@8356
    97
        SDL_SetError("Passed a NULL condition variable");
dludwig@8356
    98
        return -1;
dludwig@8356
    99
    }
dludwig@8356
   100
dludwig@8360
   101
    try {
dludwig@8360
   102
        cond->cpp_cond.notify_all();
dludwig@8360
   103
        return 0;
dludwig@8360
   104
    } catch (...) {
dludwig@8360
   105
        // catch any and all exceptions, just in case something happens
dludwig@8360
   106
        SDL_SetError("unable to broadcast C++ condition variable due to an unknown exception");
dludwig@8360
   107
        return -1;
dludwig@8356
   108
    }
dludwig@8356
   109
}
dludwig@8356
   110
dludwig@8356
   111
/* Wait on the condition variable for at most 'ms' milliseconds.
dludwig@8356
   112
   The mutex must be locked before entering this function!
dludwig@8356
   113
   The mutex is unlocked during the wait, and locked again after the wait.
dludwig@8356
   114
dludwig@8356
   115
Typical use:
dludwig@8356
   116
dludwig@8356
   117
Thread A:
dludwig@8356
   118
    SDL_LockMutex(lock);
dludwig@8356
   119
    while ( ! condition ) {
dludwig@8356
   120
        SDL_CondWait(cond, lock);
dludwig@8356
   121
    }
dludwig@8356
   122
    SDL_UnlockMutex(lock);
dludwig@8356
   123
dludwig@8356
   124
Thread B:
dludwig@8356
   125
    SDL_LockMutex(lock);
dludwig@8356
   126
    ...
dludwig@8356
   127
    condition = true;
dludwig@8356
   128
    ...
dludwig@8356
   129
    SDL_CondSignal(cond);
dludwig@8356
   130
    SDL_UnlockMutex(lock);
dludwig@8356
   131
 */
dludwig@8357
   132
extern "C"
dludwig@8356
   133
int
dludwig@8356
   134
SDL_CondWaitTimeout(SDL_cond * cond, SDL_mutex * mutex, Uint32 ms)
dludwig@8356
   135
{
dludwig@8356
   136
    if (!cond) {
dludwig@8356
   137
        SDL_SetError("Passed a NULL condition variable");
dludwig@8356
   138
        return -1;
dludwig@8356
   139
    }
dludwig@8356
   140
dludwig@8360
   141
    if (!mutex) {
dludwig@8360
   142
        SDL_SetError("Passed a NULL mutex variable");
dludwig@8360
   143
        return -1;
dludwig@8356
   144
    }
dludwig@8356
   145
dludwig@8360
   146
    try {
dludwig@8360
   147
        std::unique_lock<std::recursive_mutex> cpp_lock(mutex->cpp_mutex, std::defer_lock_t());
dludwig@8360
   148
        if (ms == SDL_MUTEX_MAXWAIT) {
dludwig@8360
   149
            cond->cpp_cond.wait(
dludwig@8360
   150
                cpp_lock
dludwig@8360
   151
                );
dludwig@8360
   152
            cpp_lock.release();
dludwig@8360
   153
            return 0;
dludwig@8360
   154
        } else {
dludwig@8360
   155
            auto wait_result = cond->cpp_cond.wait_for(
dludwig@8360
   156
                cpp_lock,
dludwig@8360
   157
                std::chrono::duration<Uint32, std::milli>(ms)
dludwig@8360
   158
                );
dludwig@8360
   159
            cpp_lock.release();
dludwig@8360
   160
            if (wait_result == std::cv_status::timeout) {
dludwig@8360
   161
                return SDL_MUTEX_TIMEDOUT;
dludwig@8360
   162
            } else {
dludwig@8360
   163
                return 0;
dludwig@8360
   164
            }
dludwig@8356
   165
        }
dludwig@8360
   166
    } catch (std::exception & ex) {
dludwig@8360
   167
        SDL_SetError("unable to wait on C++ condition variable: %s", ex.what());
dludwig@8360
   168
        return -1;
dludwig@8360
   169
    } catch (...) {
dludwig@8360
   170
        SDL_SetError("unable to lock wait on C++ condition variable due to an unknown exception");
dludwig@8360
   171
        return -1;
dludwig@8356
   172
    }
dludwig@8356
   173
}
dludwig@8356
   174
dludwig@8356
   175
/* Wait on the condition variable forever */
dludwig@8357
   176
extern "C"
dludwig@8356
   177
int
dludwig@8356
   178
SDL_CondWait(SDL_cond * cond, SDL_mutex * mutex)
dludwig@8356
   179
{
dludwig@8356
   180
    return SDL_CondWaitTimeout(cond, mutex, SDL_MUTEX_MAXWAIT);
dludwig@8356
   181
}
dludwig@8356
   182
dludwig@8356
   183
/* vi: set ts=4 sw=4 expandtab: */