267 lines
6.2 KiB
C++
267 lines
6.2 KiB
C++
/* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */
|
|
|
|
/*
|
|
* Main authors:
|
|
* Guido Tack <guido.tack@monash.edu>
|
|
*/
|
|
|
|
/* 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 __MINIZINC_GC_HH__
|
|
#define __MINIZINC_GC_HH__
|
|
|
|
#include <minizinc/config.hh>
|
|
#include <minizinc/timer.hh>
|
|
|
|
#include <cassert>
|
|
#include <cstdlib>
|
|
#include <new>
|
|
#include <unordered_map>
|
|
|
|
namespace MiniZinc {
|
|
|
|
/**
|
|
* \brief Base class for abstract syntax tree nodes
|
|
*/
|
|
class ASTNode {
|
|
friend class GC;
|
|
|
|
protected:
|
|
/// Mark for garbage collection
|
|
mutable unsigned int _gc_mark : 1;
|
|
/// Id of the node
|
|
unsigned int _id : 7;
|
|
/// Secondary id
|
|
unsigned int _sec_id : 7;
|
|
/// Flag
|
|
unsigned int _flag_1 : 1;
|
|
/// Flag
|
|
unsigned int _flag_2 : 1;
|
|
/// Flag
|
|
unsigned int _flag_3 : 1;
|
|
/// Flag
|
|
unsigned int _flag_4 : 1;
|
|
|
|
enum BaseNodes { NID_FL, NID_CHUNK, NID_VEC, NID_END = NID_VEC };
|
|
|
|
/// Constructor
|
|
ASTNode(unsigned int id) : _gc_mark(0), _id(id), _flag_1(0), _flag_2(0), _flag_3(0), _flag_4(0) {}
|
|
|
|
public:
|
|
/// Allocate node
|
|
void* operator new(size_t size);
|
|
|
|
/// Placement-new
|
|
void* operator new(size_t, void* n) throw() { return n; }
|
|
|
|
/// Delete node (no-op)
|
|
void operator delete(void*, size_t) throw() {}
|
|
/// Delete node (no-op)
|
|
void operator delete(void*, void*) throw() {}
|
|
|
|
/// Delete node (no-op)
|
|
void operator delete(void*) throw() {}
|
|
|
|
/// Return state of first user-defined flag
|
|
bool user_flag0(void) const { return _flag_3; }
|
|
/// Set state of first user-defined flag
|
|
void user_flag0(bool b) { _flag_3 = b; }
|
|
/// Return state of second user-defined flag
|
|
bool user_flag1(void) const { return _flag_4; }
|
|
/// Set state of second user-defined flag
|
|
void user_flag1(bool b) { _flag_4 = b; }
|
|
};
|
|
|
|
/**
|
|
* \brief Base class for unstructured garbage collected data
|
|
*/
|
|
class ASTChunk : public ASTNode {
|
|
friend class GC;
|
|
|
|
protected:
|
|
/// Allocated size
|
|
size_t _size;
|
|
/// Storage
|
|
char _data[4];
|
|
/// Constructor
|
|
ASTChunk(size_t size);
|
|
/// Actual size of object in memory
|
|
size_t memsize(void) const {
|
|
size_t s = sizeof(ASTChunk) + (_size <= 4 ? 0 : _size - 4) * sizeof(char);
|
|
s += ((8 - (s & 7)) & 7);
|
|
return s;
|
|
}
|
|
/// Allocate raw memory
|
|
static void* alloc(size_t size);
|
|
};
|
|
|
|
/**
|
|
* \brief Base class for structured garbage collected data
|
|
*/
|
|
class ASTVec : public ASTNode {
|
|
friend class GC;
|
|
|
|
protected:
|
|
/// Allocated size
|
|
size_t _size;
|
|
/// Storage
|
|
void* _data[2];
|
|
/// Constructor
|
|
ASTVec(size_t size);
|
|
/// Actual size of object in memory
|
|
size_t memsize(void) const {
|
|
size_t s = sizeof(ASTVec) + (_size <= 2 ? 0 : _size - 2) * sizeof(void*);
|
|
s += ((8 - (s & 7)) & 7);
|
|
return s;
|
|
}
|
|
/// Allocate raw memory
|
|
static void* alloc(size_t size);
|
|
};
|
|
|
|
class Model;
|
|
class Expression;
|
|
|
|
class KeepAlive;
|
|
class WeakRef;
|
|
|
|
class ASTNodeWeakMap;
|
|
|
|
/// Garbage collector
|
|
class GC {
|
|
friend class ASTNode;
|
|
friend class ASTVec;
|
|
friend class ASTChunk;
|
|
friend class KeepAlive;
|
|
friend class WeakRef;
|
|
friend class ASTNodeWeakMap;
|
|
|
|
private:
|
|
class Heap;
|
|
/// The memory controlled by the collector
|
|
Heap* _heap;
|
|
/// Count how many locks are currently active
|
|
unsigned int _lock_count;
|
|
/// Timeout in milliseconds
|
|
unsigned long long int _timeout;
|
|
/// Counter for timeout
|
|
int _timeout_counter;
|
|
/// Timer for timeout
|
|
Timer _timeout_timer;
|
|
/// Return thread-local GC object
|
|
static GC*& gc(void);
|
|
/// Constructor
|
|
GC(void);
|
|
|
|
/// Allocate garbage collected memory
|
|
void* alloc(size_t size);
|
|
|
|
static void addKeepAlive(KeepAlive* e);
|
|
static void removeKeepAlive(KeepAlive* e);
|
|
static void addWeakRef(WeakRef* e);
|
|
static void removeWeakRef(WeakRef* e);
|
|
static void addNodeWeakMap(ASTNodeWeakMap* m);
|
|
static void removeNodeWeakMap(ASTNodeWeakMap* m);
|
|
|
|
public:
|
|
/// Acquire garbage collector lock for this thread
|
|
static void lock(void);
|
|
/// Release garbage collector lock for this thread
|
|
static void unlock(void);
|
|
/// Manually trigger garbage collector (must be unlocked)
|
|
static void trigger(void);
|
|
/// Test if garbage collector is locked
|
|
static bool locked(void);
|
|
/// Add model \a m to root set
|
|
static void add(Model* m);
|
|
/// Remove model \a m from root set
|
|
static void remove(Model* m);
|
|
|
|
/// Put a mark on the trail
|
|
static void mark(void);
|
|
/// Add a trail entry
|
|
static void trail(Expression**, Expression*);
|
|
/// Untrail to previous mark
|
|
static void untrail(void);
|
|
|
|
/// Set timeout of \a t milliseconds, 0 means disable
|
|
static void setTimeout(unsigned long long int t);
|
|
|
|
/// Return maximum allocated memory (high water mark)
|
|
static size_t maxMem(void);
|
|
};
|
|
|
|
/// Automatic garbage collection lock
|
|
class GCLock {
|
|
public:
|
|
/// Acquire lock
|
|
GCLock(void);
|
|
/// Release lock upon destruction
|
|
~GCLock(void);
|
|
};
|
|
|
|
/// Expression wrapper that is a member of the root set
|
|
class KeepAlive {
|
|
friend class GC;
|
|
|
|
private:
|
|
Expression* _e;
|
|
KeepAlive* _p;
|
|
KeepAlive* _n;
|
|
|
|
public:
|
|
KeepAlive(Expression* e = NULL);
|
|
~KeepAlive(void);
|
|
KeepAlive(const KeepAlive& e);
|
|
KeepAlive& operator=(const KeepAlive& e);
|
|
Expression* operator()(void) { return _e; }
|
|
Expression* operator()(void) const { return _e; }
|
|
KeepAlive* next(void) const { return _n; }
|
|
};
|
|
|
|
/// Expression wrapper that is a member of the root set
|
|
class WeakRef {
|
|
friend class GC;
|
|
|
|
private:
|
|
Expression* _e;
|
|
WeakRef* _p;
|
|
WeakRef* _n;
|
|
bool _valid;
|
|
|
|
public:
|
|
WeakRef(Expression* e = NULL);
|
|
~WeakRef(void);
|
|
WeakRef(const WeakRef& e);
|
|
WeakRef& operator=(const WeakRef& e);
|
|
Expression* operator()(void) { return _valid ? _e : NULL; }
|
|
Expression* operator()(void) const { return _valid ? _e : NULL; }
|
|
WeakRef* next(void) const { return _n; }
|
|
};
|
|
|
|
class ASTNodeWeakMap {
|
|
friend class GC;
|
|
|
|
private:
|
|
ASTNodeWeakMap(const WeakRef& e);
|
|
ASTNodeWeakMap& operator=(const ASTNodeWeakMap& e);
|
|
|
|
protected:
|
|
typedef std::unordered_map<ASTNode*, ASTNode*> NodeMap;
|
|
ASTNodeWeakMap* _p;
|
|
ASTNodeWeakMap* _n;
|
|
ASTNodeWeakMap* next(void) const { return _n; }
|
|
NodeMap _m;
|
|
|
|
public:
|
|
ASTNodeWeakMap(void);
|
|
~ASTNodeWeakMap(void);
|
|
void insert(ASTNode* n0, ASTNode* n1);
|
|
ASTNode* find(ASTNode* n);
|
|
void clear() { _m.clear(); }
|
|
};
|
|
} // namespace MiniZinc
|
|
|
|
#endif
|