Colobot
resource_owning_thread.h
1 /*
2  * This file is part of the Colobot: Gold Edition source code
3  * Copyright (C) 2001-2015, Daniel Roux, EPSITEC SA & TerranovaTeam
4  * http://epsitec.ch; http://colobot.info; http://github.com/colobot
5  *
6  * This program is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14  * See the GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program. If not, see http://gnu.org/licenses
18  */
19 
20 #pragma once
21 
22 #include "common/thread/sdl_cond_wrapper.h"
23 #include "common/thread/sdl_mutex_wrapper.h"
24 
25 #include <SDL_thread.h>
26 
27 #include <memory>
28 
48 template<typename Resource>
50 {
51 public:
52  using ResourceUPtr = std::unique_ptr<Resource>;
53  using ThreadFunctionPtr = void(*)(ResourceUPtr);
54 
55  CResourceOwningThread(ThreadFunctionPtr threadFunction, ResourceUPtr resource)
56  : m_threadFunction(threadFunction),
57  m_resource(std::move(resource))
58  {}
59 
60  void Start()
61  {
62  CSDLMutexWrapper mutex;
63  CSDLCondWrapper cond;
64  bool condition = false;
65 
66  ThreadData data;
67  data.resource = std::move(m_resource);
68  data.threadFunction = m_threadFunction;
69  data.mutex = &mutex;
70  data.cond = &cond;
71  data.condition = &condition;
72 
73  SDL_LockMutex(*mutex);
74 
75  SDL_CreateThread(Run, reinterpret_cast<void*>(&data));
76 
77  while (!condition)
78  {
79  SDL_CondWait(*cond, *mutex);
80  }
81 
82  SDL_UnlockMutex(*mutex);
83  }
84 
85 private:
86  static int Run(void* data)
87  {
88  ThreadFunctionPtr threadFunction = nullptr;
89  ResourceUPtr resource;
90 
91  ThreadData* threadData = reinterpret_cast<ThreadData*>(data);
92  SDL_LockMutex(**threadData->mutex);
93 
94  threadFunction = threadData->threadFunction;
95  resource = std::move(threadData->resource);
96 
97  *threadData->condition = true;
98  SDL_CondSignal(**threadData->cond);
99  SDL_UnlockMutex(**threadData->mutex);
100 
101  threadFunction(std::move(resource));
102  return 0;
103  }
104 
105 private:
106  struct ThreadData
107  {
108  ResourceUPtr resource;
109  CSDLMutexWrapper* mutex = nullptr;
110  CSDLCondWrapper* cond = nullptr;
111  bool* condition = nullptr;
112  ThreadFunctionPtr threadFunction = nullptr;
113  };
114 
115  ThreadFunctionPtr m_threadFunction;
116  ResourceUPtr m_resource;
117 };
Wrapper around SDL thread allowing passing of resources in safe manner.
Definition: resource_owning_thread.h:49
Wrapper for safe creation/deletion of SDL_cond.
Definition: sdl_cond_wrapper.h:28
Wrapper for safe creation/deletion of SDL_mutex.
Definition: sdl_mutex_wrapper.h:28