src/thread/stdcpp/SDL_syscond.cpp
author Sam Lantinga <slouken@libsdl.org>
Thu, 13 Mar 2014 00:40:08 -0700
changeset 8615 097646deaef2
parent 8600 092802455aed
child 9619 b94b6d0bff0f
permissions -rw-r--r--
Fixed the copyright date on files contributed by David Ludwig
dludwig@8356
     1
/*
dludwig@8356
     2
  Simple DirectMedia Layer
slouken@8615
     3
  Copyright (C) 1997-2014 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@8600
    21
#include "../../SDL_internal.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 <ratio>
dludwig@8484
    30
#include <system_error>
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@8484
    48
    } catch (std::system_error & ex) {
dludwig@8484
    49
        SDL_SetError("unable to create a C++ condition variable: code=%d; %s", ex.code(), ex.what());
dludwig@8360
    50
        return NULL;
dludwig@8484
    51
    } catch (std::bad_alloc &) {
dludwig@8484
    52
        SDL_OutOfMemory();
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@8484
    63
        delete cond;
dludwig@8356
    64
    }
dludwig@8356
    65
}
dludwig@8356
    66
dludwig@8356
    67
/* Restart one of the threads that are waiting on the condition variable */
dludwig@8357
    68
extern "C"
dludwig@8356
    69
int
dludwig@8356
    70
SDL_CondSignal(SDL_cond * cond)
dludwig@8356
    71
{
dludwig@8356
    72
    if (!cond) {
dludwig@8356
    73
        SDL_SetError("Passed a NULL condition variable");
dludwig@8356
    74
        return -1;
dludwig@8356
    75
    }
dludwig@8356
    76
dludwig@8484
    77
    cond->cpp_cond.notify_one();
dludwig@8484
    78
    return 0;
dludwig@8356
    79
}
dludwig@8356
    80
dludwig@8356
    81
/* Restart all threads that are waiting on the condition variable */
dludwig@8357
    82
extern "C"
dludwig@8356
    83
int
dludwig@8356
    84
SDL_CondBroadcast(SDL_cond * cond)
dludwig@8356
    85
{
dludwig@8356
    86
    if (!cond) {
dludwig@8356
    87
        SDL_SetError("Passed a NULL condition variable");
dludwig@8356
    88
        return -1;
dludwig@8356
    89
    }
dludwig@8356
    90
dludwig@8484
    91
    cond->cpp_cond.notify_all();
dludwig@8484
    92
    return 0;
dludwig@8356
    93
}
dludwig@8356
    94
dludwig@8356
    95
/* Wait on the condition variable for at most 'ms' milliseconds.
dludwig@8356
    96
   The mutex must be locked before entering this function!
dludwig@8356
    97
   The mutex is unlocked during the wait, and locked again after the wait.
dludwig@8356
    98
dludwig@8356
    99
Typical use:
dludwig@8356
   100
dludwig@8356
   101
Thread A:
dludwig@8356
   102
    SDL_LockMutex(lock);
dludwig@8356
   103
    while ( ! condition ) {
dludwig@8356
   104
        SDL_CondWait(cond, lock);
dludwig@8356
   105
    }
dludwig@8356
   106
    SDL_UnlockMutex(lock);
dludwig@8356
   107
dludwig@8356
   108
Thread B:
dludwig@8356
   109
    SDL_LockMutex(lock);
dludwig@8356
   110
    ...
dludwig@8356
   111
    condition = true;
dludwig@8356
   112
    ...
dludwig@8356
   113
    SDL_CondSignal(cond);
dludwig@8356
   114
    SDL_UnlockMutex(lock);
dludwig@8356
   115
 */
dludwig@8357
   116
extern "C"
dludwig@8356
   117
int
dludwig@8356
   118
SDL_CondWaitTimeout(SDL_cond * cond, SDL_mutex * mutex, Uint32 ms)
dludwig@8356
   119
{
dludwig@8356
   120
    if (!cond) {
dludwig@8356
   121
        SDL_SetError("Passed a NULL condition variable");
dludwig@8356
   122
        return -1;
dludwig@8356
   123
    }
dludwig@8356
   124
dludwig@8360
   125
    if (!mutex) {
dludwig@8360
   126
        SDL_SetError("Passed a NULL mutex variable");
dludwig@8360
   127
        return -1;
dludwig@8356
   128
    }
dludwig@8356
   129
dludwig@8360
   130
    try {
dludwig@8360
   131
        std::unique_lock<std::recursive_mutex> cpp_lock(mutex->cpp_mutex, std::defer_lock_t());
dludwig@8360
   132
        if (ms == SDL_MUTEX_MAXWAIT) {
dludwig@8360
   133
            cond->cpp_cond.wait(
dludwig@8360
   134
                cpp_lock
dludwig@8360
   135
                );
dludwig@8360
   136
            cpp_lock.release();
dludwig@8360
   137
            return 0;
dludwig@8360
   138
        } else {
dludwig@8360
   139
            auto wait_result = cond->cpp_cond.wait_for(
dludwig@8360
   140
                cpp_lock,
dludwig@8360
   141
                std::chrono::duration<Uint32, std::milli>(ms)
dludwig@8360
   142
                );
dludwig@8360
   143
            cpp_lock.release();
dludwig@8360
   144
            if (wait_result == std::cv_status::timeout) {
dludwig@8360
   145
                return SDL_MUTEX_TIMEDOUT;
dludwig@8360
   146
            } else {
dludwig@8360
   147
                return 0;
dludwig@8360
   148
            }
dludwig@8356
   149
        }
dludwig@8484
   150
    } catch (std::system_error & ex) {
dludwig@8484
   151
        SDL_SetError("unable to wait on a C++ condition variable: code=%d; %s", ex.code(), ex.what());
dludwig@8360
   152
        return -1;
dludwig@8356
   153
    }
dludwig@8356
   154
}
dludwig@8356
   155
dludwig@8356
   156
/* Wait on the condition variable forever */
dludwig@8357
   157
extern "C"
dludwig@8356
   158
int
dludwig@8356
   159
SDL_CondWait(SDL_cond * cond, SDL_mutex * mutex)
dludwig@8356
   160
{
dludwig@8356
   161
    return SDL_CondWaitTimeout(cond, mutex, SDL_MUTEX_MAXWAIT);
dludwig@8356
   162
}
dludwig@8356
   163
dludwig@8356
   164
/* vi: set ts=4 sw=4 expandtab: */