TuringSim
C++ framework to simulate abstract computing models
memoryStructure.h
1 #pragma once
2 
3 #include <utils/messageException.h>
4 
5 #include <set>
6 #include <sstream>
7 
11 namespace TuringSim{
12 }
13 
17 namespace TuringSim::Memory {
18 
23  public:
27 
32  InvalidFactorException(std::string message, size_t sizeFactor) : MessageException(message), sizeFactor(sizeFactor) {}
33 
37  size_t getIllegalSizeFactor() const noexcept {
38  return sizeFactor;
39  }
40  protected:
41  virtual std::string makeFullMessage() const override {
42  std::ostringstream ss;
43  ss << this->msg << std::endl;
44  ss << " size factor: " << sizeFactor << std::endl;
45  return ss.str();
46  }
47 
48  size_t sizeFactor;
49  };
50 
56  template<typename Memory, typename Modifier>
58  public:
62 
68  ExistingModifierException(std::string message, const Memory* memory, const Modifier* modifier) :
70  }
71 
75  const Memory* getMemory() const {
76  return memory;
77  }
78 
82  const Modifier* getModifier() const {
83  return modifier;
84  }
85 
86  protected:
87  virtual std::string makeFullMessage() const override {
88  std::ostringstream ss;
89  ss << this->msg << std::endl;
90  ss << " memory structure address: " << memory << std::endl;
91  ss << " existing modifier address: " << modifier << std::endl;
92  return ss.str();
93  }
94  const Memory* memory;
95  const Modifier* modifier;
96  };
97 
98  template <typename D, typename O>
99  class MemoryObserver;
100  template <typename D, typename M>
101  class MemoryModifier;
102 
116  template <typename T, typename D, typename O, typename M>
118  public:
119  typedef O Observer;
120  typedef M Modifier;
121  static_assert(std::is_base_of_v<MemoryObserver<D, O>, O>);
122  static_assert(std::is_base_of_v<MemoryModifier<D, M>, M>);
123  friend class MemoryObserver<D, O>;
124  friend class MemoryModifier<D, M>;
127  friend Observer;
130  friend Modifier;
135  typedef T SymbolType;
136 
140  for(Observer* observer: observers) {
141  observer->unsafe_release();
142  }
143  if(modifier) {
144  (*modifier)->unsafe_release();
145  }
146  }
147 
151  const std::set<Observer*>& getObservers() const noexcept {
152  return observers;
153  }
154 
158  const std::optional<Modifier*>& getModifier() const noexcept {
159  return modifier;
160  }
161 
162  private:
168  mutable std::set<Observer*> observers;
169 
174  mutable std::optional<Modifier*> modifier;
175  };
176 
186  template <typename Memory, typename Observer>
188  public:
190  MemoryObserver() noexcept : memory(nullptr) {}
191 
195  MemoryObserver(const Memory* memory) : MemoryObserver() {
196  acquire(memory);
197  }
198 
205  acquire(other->memory);
206  }
207 
214  acquire(other->memory);
215  other.release();
216  }
217 
223  if(this != &other) {
224  acquire(other->memory);
225  }
226  return *this;
227  }
228 
234  if(this != &other) {
235  acquire(other->memory);
236  other.release();
237  }
238  return *this;
239  }
240 
244  release();
245  }
246 
253  void acquire(const Memory* toAcquire) {
254  if(memory == toAcquire){
255  return;
256  }
257  release();
258  if(toAcquire != nullptr) {
259  memory = toAcquire;
260  memory->observers.insert(static_cast<Observer*>(this));
261  }
262  }
263 
268  void unsafe_release() {
269  memory->observers.erase(static_cast<Observer*>(this));
270  memory = nullptr;
271  }
272 
275  void release() {
276  if(memory != nullptr) {
277  unsafe_release();
278  }
279  }
280 
284  bool empty() const noexcept {
285  return memory == nullptr;
286  }
287 
288  protected:
294  const Memory* memory;
295  };
296 
306  template <typename Memory, typename Modifier>
308  public:
311  MemoryModifier() : memory(nullptr) {}
316  acquire(m);
317  }
318 
321  MemoryModifier(const MemoryModifier& other) = delete;
322 
329  Memory* otherMemory = other->memory;
330  other.release();
331  acquire(otherMemory);
332  }
333 
337 
343  if(this != &other) {
344  Memory* otherMemory = other->memory;
345  other.release();
346  acquire(otherMemory);
347  }
348  return *this;
349  }
350 
354  release();
355  }
356 
366  void acquire(Memory* toAcquire) {
367  if(memory == toAcquire) {
368  return;
369  }
370  if(toAcquire->modifier) {
371  throw ExistingModifierException("Memory structure already has a modifier", toAcquire, *toAcquire->modifier);
372  }
373  release();
374  if(toAcquire != nullptr) {
375  memory = toAcquire;
376  memory->modifier = static_cast<Modifier*>(this);
377  }
378  }
379 
386  void force_acquire(Memory* toAcquire) {
387  if(memory == toAcquire) {
388  return;
389  }
390  release();
391  if(toAcquire != nullptr) {
392  if (toAcquire->modifier) {
393  (*toAcquire->modifier)->release();
394  }
395  memory = toAcquire;
396  memory->modifier = static_cast<Modifier*>(this);
397  }
398  }
399 
404  void unsafe_release() {
405  memory->modifier.reset();
406  memory = nullptr;
407  }
408 
411  void release() {
412  if(memory != nullptr) {
413  unsafe_release();
414  }
415  }
416 
420  bool empty() const noexcept {
421  return memory == nullptr;
422  }
423 
424  protected:
430  Memory* memory;
431  };
432 }
TuringSim::Memory::MemoryModifier::unsafe_release
void unsafe_release()
Releases the current observed memory, without checking if there is some.
Definition: memoryStructure.h:404
TuringSim::Utils::MessageException::MessageException
MessageException()=delete
a message exception must have an explicative message.
TuringSim::Memory::ExistingModifierException::getModifier
const Modifier * getModifier() const
Access the existing modifier.
Definition: memoryStructure.h:82
TuringSim::Memory::InvalidFactorException::sizeFactor
size_t sizeFactor
The illegal factor.
Definition: memoryStructure.h:48
TuringSim::Memory::MemoryModifier::operator=
MemoryModifier & operator=(MemoryModifier &&other)
Move assignment operator.
Definition: memoryStructure.h:342
TuringSim::Memory::MemoryStructure::getObservers
const std::set< Observer * > & getObservers() const noexcept
Gets the set of observers.
Definition: memoryStructure.h:151
TuringSim::Memory::MemoryObserver::operator=
MemoryObserver & operator=(MemoryObserver &&other)
Move assignment operator.
Definition: memoryStructure.h:233
TuringSim::Utils::MessageException::msg
std::string msg
The error message.
Definition: messageException.h:78
TuringSim::Memory::InvalidFactorException::getIllegalSizeFactor
size_t getIllegalSizeFactor() const noexcept
Return the illegal factor.
Definition: memoryStructure.h:37
TuringSim::Memory::MemoryStructure::Modifier
friend Modifier
Modifier class.
Definition: memoryStructure.h:130
TuringSim::Utils::MessageException
The Base class for all custom exceptions.
Definition: messageException.h:12
TuringSim::Memory::ExistingModifierException::getMemory
const Memory * getMemory() const
Access the memory structure.
Definition: memoryStructure.h:75
TuringSim::Memory::MemoryModifier::MemoryModifier
MemoryModifier()
Default constructor that binds no memory structure.
Definition: memoryStructure.h:311
TuringSim::Memory::MemoryStructure::Observer
friend Observer
Observer class.
Definition: memoryStructure.h:127
TuringSim::Memory::InvalidFactorException::makeFullMessage
virtual std::string makeFullMessage() const override
Build the full error message. It should be overridden by derived class that adds data to the exceptio...
Definition: memoryStructure.h:41
TuringSim::Memory::MemoryObserver::acquire
void acquire(const Memory *toAcquire)
Observe a new memory structure.
Definition: memoryStructure.h:253
TuringSim::Memory::InvalidFactorException
Exception thrown when a size factor is set to an illegal value.
Definition: memoryStructure.h:22
TuringSim::Memory::MemoryObserver::~MemoryObserver
~MemoryObserver()
Destruct an observer and release the memory structure.
Definition: memoryStructure.h:243
TuringSim
Namespace for all component of the framework.
Definition: deterministicCounterListener.h:6
TuringSim::Memory::MemoryObserver::operator=
MemoryObserver & operator=(MemoryObserver &other)
Copy assignment operator.
Definition: memoryStructure.h:222
TuringSim::Memory::MemoryStructure::SymbolType
T SymbolType
The alphabet type.
Definition: memoryStructure.h:135
TuringSim::Memory::MemoryModifier::MemoryModifier
MemoryModifier(const MemoryModifier &other)=delete
Copy constructor is deleted because a memory structure should have only one modifier.
TuringSim::Memory::MemoryModifier::acquire
void acquire(Memory *toAcquire)
Bind a new memory structure.
Definition: memoryStructure.h:366
TuringSim::Memory::MemoryModifier::memory
Memory * memory
The observed memory.
Definition: memoryStructure.h:430
TuringSim::Memory::MemoryModifier::release
void release()
Releases the current bounded memory if there is one. Otherwise, does nothing.
Definition: memoryStructure.h:411
TuringSim::Memory::MemoryObserver::memory
const Memory * memory
The observed memory.
Definition: memoryStructure.h:294
TuringSim::Memory::MemoryObserver::empty
bool empty() const noexcept
Check if *this observes a memory.
Definition: memoryStructure.h:284
TuringSim::Memory::MemoryStructure::getModifier
const std::optional< Modifier * > & getModifier() const noexcept
Gets the optional modifier.
Definition: memoryStructure.h:158
TuringSim::Memory::MemoryObserver::unsafe_release
void unsafe_release()
Releases the current observed memory, without checking if there is some.
Definition: memoryStructure.h:268
TuringSim::Memory::MemoryStructure
Base class for all memory structures.
Definition: memoryStructure.h:117
TuringSim::Memory::InvalidFactorException::InvalidFactorException
InvalidFactorException(std::string message, size_t sizeFactor)
Build an InvalidFactorException from an error message and an offending size factor.
Definition: memoryStructure.h:32
TuringSim::Memory::ExistingModifierException::ExistingModifierException
ExistingModifierException(std::string message, const Memory *memory, const Modifier *modifier)
Build an ExistingModifierException from an error message, a pointer to the memory structure,...
Definition: memoryStructure.h:68
TuringSim::Memory::MemoryModifier::~MemoryModifier
~MemoryModifier()
Destruct a modifier and release the memory structure.
Definition: memoryStructure.h:353
TuringSim::Memory::MemoryModifier::MemoryModifier
MemoryModifier(MemoryModifier &&other)
Move constructor.
Definition: memoryStructure.h:328
TuringSim::Memory::MemoryObserver::MemoryObserver
MemoryObserver(MemoryObserver &&other)
Move constructor.
Definition: memoryStructure.h:213
TuringSim::Memory::MemoryObserver::MemoryObserver
MemoryObserver(const MemoryObserver &other)
Build a new observer to the same memory.
Definition: memoryStructure.h:204
TuringSim::Memory::InvalidFactorException::InvalidFactorException
InvalidFactorException()=delete
An InvalidFactorException must contain an error message and the offending size factor.
TuringSim::Memory::ExistingModifierException::memory
const Memory * memory
The involved memory structure.
Definition: memoryStructure.h:94
TuringSim::Memory::MemoryStructure::Observer
O Observer
The type of observers.
Definition: memoryStructure.h:119
TuringSim::Memory::MemoryObserver::MemoryObserver
MemoryObserver(const Memory *memory)
Build an observer that observes a given memory.
Definition: memoryStructure.h:195
TuringSim::Memory::MemoryObserver::release
void release()
Releases the current observed memory if there is one. Otherwise, does nothing.
Definition: memoryStructure.h:275
TuringSim::Memory::ExistingModifierException
Exception thrown when attempting to bound a modifier to a memory structure that is already bound to a...
Definition: memoryStructure.h:57
TuringSim::Memory::ExistingModifierException::modifier
const Modifier * modifier
The other modifier.
Definition: memoryStructure.h:95
TuringSim::Memory::ExistingModifierException::makeFullMessage
virtual std::string makeFullMessage() const override
Build the full error message. It should be overridden by derived class that adds data to the exceptio...
Definition: memoryStructure.h:87
TuringSim::Memory::MemoryModifier::operator=
MemoryModifier & operator=(MemoryModifier &)=delete
Copy assignment operator is deleted because a memory structure should have only one modifier.
TuringSim::Memory::MemoryObserver
Base class for all memory observers.
Definition: memoryStructure.h:187
TuringSim::Memory::MemoryModifier::MemoryModifier
MemoryModifier(Memory *m)
Constructor that binds to a memory structure.
Definition: memoryStructure.h:315
TuringSim::Memory::MemoryModifier
Base class for all memory modifiers.
Definition: memoryStructure.h:307
TuringSim::Memory::ExistingModifierException::ExistingModifierException
ExistingModifierException()=delete
An ExistingModifierException must contain an error message, a pointer to the memory structure,...
TuringSim::Memory
Memory structures used by machines, such as tapes, stacks...
TuringSim::Memory::MemoryStructure::~MemoryStructure
~MemoryStructure()
Release current observers and modifier.
Definition: memoryStructure.h:139
TuringSim::Memory::MemoryObserver::MemoryObserver
MemoryObserver() noexcept
Build an observer that observes nothing.
Definition: memoryStructure.h:190
TuringSim::Memory::MemoryModifier::empty
bool empty() const noexcept
Check if *this is bounded to a memory.
Definition: memoryStructure.h:420
TuringSim::Memory::MemoryStructure::Modifier
M Modifier
The type of modifiers.
Definition: memoryStructure.h:120
TuringSim::Memory::MemoryModifier::force_acquire
void force_acquire(Memory *toAcquire)
Bind a new memory structure.
Definition: memoryStructure.h:386