Colobot
resource_owning_thread.h
1 /*
2  * This file is part of the Colobot: Gold Edition source code
3  * Copyright (C) 2001-2016, 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 #include <string>
29 
49 template<typename Resource>
51 {
52 public:
53  using ResourceUPtr = std::unique_ptr<Resource>;
54  using ThreadFunctionPtr = void(*)(ResourceUPtr);
55 
56  CResourceOwningThread(ThreadFunctionPtr threadFunction, ResourceUPtr resource, std::string name = "")
57  : m_threadFunction(threadFunction),
58  m_resource(std::move(resource)),
59  m_name(name)
60  {}
61 
62  void Start()
63  {
64  CSDLMutexWrapper mutex;
65  CSDLCondWrapper cond;
66  bool condition = false;
67 
68  ThreadData data;
69  data.resource = std::move(m_resource);
70  data.threadFunction = m_threadFunction;
71  data.mutex = &mutex;
72  data.cond = &cond;
73  data.condition = &condition;
74 
75  SDL_LockMutex(*mutex);
76 
77  SDL_CreateThread(Run, !m_name.empty() ? m_name.c_str() : nullptr, reinterpret_cast<void*>(&data));
78 
79  while (!condition)
80  {
81  SDL_CondWait(*cond, *mutex);
82  }
83 
84  SDL_UnlockMutex(*mutex);
85  }
86 
87 private:
88  static int Run(void* data)
89  {
90  ThreadFunctionPtr threadFunction = nullptr;
91  ResourceUPtr resource;
92 
93  ThreadData* threadData = reinterpret_cast<ThreadData*>(data);
94  SDL_LockMutex(**threadData->mutex);
95 
96  threadFunction = threadData->threadFunction;
97  resource = std::move(threadData->resource);
98 
99  *threadData->condition = true;
100  SDL_CondSignal(**threadData->cond);
101  SDL_UnlockMutex(**threadData->mutex);
102 
103  threadFunction(std::move(resource));
104  return 0;
105  }
106 
107 private:
108  struct ThreadData
109  {
110  ResourceUPtr resource;
111  CSDLMutexWrapper* mutex = nullptr;
112  CSDLCondWrapper* cond = nullptr;
113  bool* condition = nullptr;
114  ThreadFunctionPtr threadFunction = nullptr;
115  };
116 
117  ThreadFunctionPtr m_threadFunction;
118  ResourceUPtr m_resource;
119  std::string m_name;
120 };
Wrapper around SDL thread allowing passing of resources in safe manner.
Definition: resource_owning_thread.h:50
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