]> git.tdb.fi Git - libs/game.git/blob - source/game/component.h
Enforce correct access to buffered components
[libs/game.git] / source / game / component.h
1 #ifndef MSP_GAME_COMPONENT_H_
2 #define MSP_GAME_COMPONENT_H_
3
4 #include <msp/time/timedelta.h>
5 #include "accessguard.h"
6 #include "handle.h"
7
8 namespace Msp::Game {
9
10 class Entity;
11
12 class Component
13 {
14 protected:
15         Handle<Entity> entity;
16
17         Component(Handle<Entity>);
18 public:
19         virtual ~Component() = default;
20
21         Handle<Entity> get_entity() const { return entity; }
22 };
23
24 template<typename T>
25 class BufferedComponent: public Component
26 {
27 public:
28         using Data = T;
29         
30 protected:
31         T data[2];
32         uint8_t read_index = 0;
33         uint8_t write_index = 0;
34         bool written = false;
35
36         BufferedComponent(Handle<Entity> e): Component(e) { }
37
38         const T &read() const;
39         T &write();
40
41 public:
42         virtual void prepare_tick() { write_index = 1-read_index; written = false; }
43         virtual void commit_tick() { if(written) read_index = write_index; }
44 };
45
46 template<typename T>
47 const T &BufferedComponent<T>::read() const
48 {
49 #ifdef DEBUG
50         AccessGuard::get_instance().check<AccessGuard::Read<T>>();
51 #endif
52         return data[read_index];
53 }
54
55 template<typename T>
56 T &BufferedComponent<T>::write()
57 {
58 #ifdef DEBUG
59         AccessGuard::get_instance().check<AccessGuard::Write<T>>();
60 #endif
61         if(!written && write_index!=read_index)
62         {
63                 data[write_index] = data[read_index];
64                 written = true;
65         }
66         return data[write_index];
67 }
68
69 } // namespace Msp::Game
70
71 #endif