forked from firleju/maszyna
-
Notifications
You must be signed in to change notification settings - Fork 2
/
PyInt.h
145 lines (123 loc) · 3.72 KB
/
PyInt.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
/*
This Source Code Form is subject to the
terms of the Mozilla Public License, v.
2.0. If a copy of the MPL was not
distributed with this file, You can
obtain one at
http://mozilla.org/MPL/2.0/.
*/
#ifndef PYINT_H
#define PYINT_H
#ifdef _POSIX_C_SOURCE
#undef _POSIX_C_SOURCE
#endif
#ifdef _XOPEN_SOURCE
#undef _XOPEN_SOURCE
#endif
#ifdef _MSC_VER
#pragma warning( push )
#pragma warning( disable : 5033 )
#endif
#ifdef __GNUC__
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wregister"
#endif
#ifdef _DEBUG
#undef _DEBUG // bez tego macra Py_DECREF powoduja problemy przy linkowaniu
#include "Python.h"
#define _DEBUG
#else
#include "Python.h"
#endif
#ifdef __GNUC__
#pragma GCC diagnostic pop
#endif
#ifdef _MSC_VER
#pragma warning( pop )
#endif
#include "Classes.h"
#include "utilities.h"
#define PyGetFloat(param) PyFloat_FromDouble(param)
#define PyGetInt(param) PyInt_FromLong(param)
#define PyGetBool(param) param ? Py_True : Py_False
#define PyGetString(param) PyString_FromString(param)
// python rendertarget
struct python_rt {
std::mutex mutex;
GLuint shared_tex;
int format;
int components;
int width;
int height;
unsigned char *image = nullptr;
std::chrono::high_resolution_clock::time_point timestamp;
~python_rt() {
if (image)
delete[] image;
}
};
// TODO: extract common base and inherit specialization from it
class render_task {
public:
// constructors
render_task( PyObject *Renderer, dictionary_source *Input, std::shared_ptr<python_rt> Target ) :
m_renderer( Renderer ), m_input( Input ), m_target( Target )
{}
// methods
void run();
void upload();
void cancel();
auto target() const -> std::shared_ptr<python_rt> { return m_target; }
private:
// members
PyObject *m_renderer {nullptr};
dictionary_source *m_input { nullptr };
std::shared_ptr<python_rt> m_target { nullptr };
};
class python_taskqueue {
public:
// types
struct task_request {
std::string const &renderer;
dictionary_source *input;
std::shared_ptr<python_rt> target;
};
// constructors
python_taskqueue() = default;
// methods
// initializes the module. returns true on success
auto init() -> bool;
// shuts down the module
void exit();
// adds specified task along with provided collection of data to the work queue. returns true on success
auto insert( task_request const &Task ) -> bool;
// executes python script stored in specified file. returns true on success
auto run_file( std::string const &File, std::string const &Path = "" ) -> bool;
// acquires the python gil and sets the main thread as current
void acquire_lock();
// releases the python gil and swaps the main thread out
void release_lock();
void update();
private:
// types
static int const WORKERCOUNT { 1 };
using worker_array = std::array<std::thread, WORKERCOUNT >;
using rendertask_sequence = threading::lockable< std::deque<render_task *> >;
using uploadtask_sequence = threading::lockable< std::deque<render_task *> >;
// methods
auto fetch_renderer( std::string const Renderer ) -> PyObject *;
void run(GLFWwindow *Context, rendertask_sequence &Tasks, uploadtask_sequence &Upload_Tasks, threading::condition_variable &Condition, std::atomic<bool> &Exit );
void error();
// members
PyObject *m_main { nullptr };
PyObject *m_stderr { nullptr };
PyThreadState *m_mainthread{ nullptr };
worker_array m_workers;
threading::condition_variable m_condition; // wakes up the workers
std::atomic<bool> m_exit { false }; // signals the workers to quit
std::unordered_map<std::string, PyObject *> m_renderers; // cache of python classes
rendertask_sequence m_tasks;
uploadtask_sequence m_uploadtasks;
bool m_initialized { false };
};
#endif