Make various instance stuff to take references to other instance objs
[lsnes.git] / src / core / instance.cpp
blobd40154e41f34c21261b09c369117d4e0f677c071
1 #include "core/instance.hpp"
2 #include "core/settings.hpp"
3 #include "core/command.hpp"
4 #include "core/keymapper.hpp"
5 #include "core/random.hpp"
6 #ifdef __linux__
7 #include <execinfo.h>
8 #endif
10 input_queue::input_queue(command::group& _command)
11 : command(_command)
13 system_thread_available = false;
14 queue_function_run = false;
17 emulator_instance::emulator_instance()
18 : mwatch(memory, project, fbuf), setcache(settings), subtitles(mlogic, fbuf), mbranch(&mlogic),
19 mteditor(mlogic, controls), status(status_A, status_B, status_C), mapper(keyboard, command),
20 abindmanager(mapper, command), cmapper(memory), controls(project, mlogic),
21 project(commentary, mwatch, command, controls, setcache), fbuf(subtitles, settings, mwatch, keyboard),
22 iqueue(command)
24 status_A.valid = false;
25 status_B.valid = false;
26 status_C.valid = false;
27 command.add_set(lsnes_cmds);
28 mapper.add_invbind_set(lsnes_invbinds);
29 settings.add_set(lsnes_setgrp);
32 emulator_instance lsnes_instance;
34 emulator_instance& CORE()
36 if(threads::id() != lsnes_instance.emu_thread) {
37 std::cerr << "WARNING: CORE() called in wrong thread." << std::endl;
38 #ifdef __linux__
39 void* arr[256];
40 backtrace_symbols_fd(arr, 256, 2);
41 #endif
43 return lsnes_instance;
46 keypress_info::keypress_info()
48 key1 = NULL;
49 key2 = NULL;
50 value = 0;
53 keypress_info::keypress_info(keyboard::modifier_set mod, keyboard::key& _key, short _value)
55 modifiers = mod;
56 key1 = &_key;
57 key2 = NULL;
58 value = _value;
61 keypress_info::keypress_info(keyboard::modifier_set mod, keyboard::key& _key, keyboard::key& _key2, short _value)
63 modifiers = mod;
64 key1 = &_key;
65 key2 = &_key2;
66 value = _value;
70 void input_queue::queue(const keypress_info& k) throw(std::bad_alloc)
72 threads::alock h(queue_lock);
73 keypresses.push_back(k);
74 queue_condition.notify_all();
77 void input_queue::queue(const std::string& c) throw(std::bad_alloc)
79 threads::alock h(queue_lock);
80 commands.push_back(c);
81 queue_condition.notify_all();
84 void input_queue::queue(std::function<void()> f, std::function<void(std::exception& e)> onerror, bool sync)
85 throw(std::bad_alloc)
87 if(!system_thread_available) {
88 try {
89 f();
90 } catch(std::exception& e) {
91 onerror(e);
93 return;
95 threads::alock h(queue_lock);
96 ++next_function;
97 function_queue_entry entry;
98 entry.fn = f;
99 entry.onerror = onerror;
100 functions.push_back(entry);
101 queue_condition.notify_all();
102 if(sync)
103 while(functions_executed < next_function && system_thread_available) {
104 threads::cv_timed_wait(queue_condition, h, threads::ustime(10000));
105 random_mix_timing_entropy();
109 void input_queue::run_queue(bool unlocked) throw()
111 if(!unlocked)
112 queue_lock.lock();
113 try {
114 //Flush keypresses.
115 while(!keypresses.empty()) {
116 keypress_info k = keypresses.front();
117 keypresses.pop_front();
118 queue_lock.unlock();
119 if(k.key1)
120 k.key1->set_state(k.modifiers, k.value);
121 if(k.key2)
122 k.key2->set_state(k.modifiers, k.value);
123 queue_lock.lock();
124 queue_function_run = true;
126 //Flush commands.
127 while(!commands.empty()) {
128 std::string c = commands.front();
129 commands.pop_front();
130 queue_lock.unlock();
131 command.invoke(c);
132 queue_lock.lock();
133 queue_function_run = true;
135 //Flush functions.
136 while(!functions.empty()) {
137 function_queue_entry f = functions.front();
138 functions.pop_front();
139 queue_lock.unlock();
140 try {
141 f.fn();
142 } catch(std::exception& e) {
143 f.onerror(e);
145 queue_lock.lock();
146 ++functions_executed;
147 queue_function_run = true;
149 queue_condition.notify_all();
150 } catch(std::bad_alloc& e) {
151 OOM_panic();
152 } catch(std::exception& e) {
153 std::cerr << "Fault inside platform::run_queues(): " << e.what() << std::endl;
154 exit(1);
156 if(!unlocked)
157 queue_lock.unlock();