dvander@29: /* vim: set ts=4 sw=4 tw=99 et: dvander@29: * dvander@28: * Copyright (C) 2012 David Anderson dvander@28: * dvander@28: * This file is part of JITCraft. dvander@28: * dvander@28: * JITCraft is free software: you can redistribute it and/or modify it under dvander@28: * the terms of the GNU General Public License as published by the Free dvander@28: * Software Foundation, either version 3 of the License, or (at your option) dvander@28: * any later version. dvander@28: * dvander@28: * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY dvander@28: * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS dvander@28: * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. dvander@28: * dvander@28: * You should have received a copy of the GNU General Public License along with dvander@28: * JITCraft. If not, see http://www.gnu.org/licenses/. dvander@28: */ dvander@28: #ifndef _include_jitcraft_rooting_h_ dvander@28: #define _include_jitcraft_rooting_h_ dvander@28: dvander@85: #include dvander@85: dvander@59: namespace ke { dvander@28: dvander@28: class Zone; dvander@60: class Object; dvander@28: dvander@11: template class Local; dvander@11: template class ScopedRoot; dvander@11: dvander@195: struct NullAddress dvander@195: { dvander@195: static void * const Sentinel; dvander@195: }; dvander@195: dvander@60: /* dvander@60: * Internal handles work differently from API handles. An API handle is a dvander@60: * root, whereas as an internal handle points to a rooted location. This dvander@60: * subtle difference makes handles easy for embedders, but somewhat dvander@60: * cumbersome internally. dvander@60: */ dvander@11: template dvander@11: class Handle dvander@11: { dvander@11: T * const *thingp_; dvander@11: dvander@195: private: dvander@195: Handle() dvander@195: : thingp_(reinterpret_cast(&NullAddress::Sentinel)) dvander@195: { dvander@195: } dvander@195: dvander@11: public: dvander@40: Handle(const Handle &other) { dvander@40: thingp_ = other.address(); dvander@40: } dvander@11: template Handle(const Handle &handle) { dvander@11: typeCheck(); dvander@28: thingp_ = reinterpret_cast(handle.address()); dvander@11: } dvander@11: template inline Handle(const Local &local); dvander@11: template inline Handle(const ScopedRoot &root); dvander@11: dvander@195: static inline Handle Null() { dvander@195: return Handle(); dvander@195: } dvander@195: dvander@11: public: dvander@11: T *operator ->() { dvander@11: return *thingp_; dvander@11: } dvander@11: T *operator *() { dvander@11: return *thingp_; dvander@11: } dvander@240: operator T *() const { return *thingp_; } dvander@11: operator bool() const { dvander@11: return thingp_ && *thingp_; dvander@11: } dvander@28: T * const *address() const { dvander@11: return thingp_; dvander@11: } dvander@11: dvander@196: bool operator ==(const Handle &other) const { dvander@196: return (!thingp_ && !other.thingp_) || dvander@196: *thingp_ == *other.thingp_; dvander@196: } dvander@233: bool operator !=(const Handle &other) const { dvander@233: return (!thingp_ != !other.thingp_) || dvander@233: *thingp_ != *other.thingp_; dvander@233: } dvander@196: dvander@11: private: dvander@11: template dvander@11: void typeCheck() { dvander@85: #ifndef NDEBUG dvander@11: T *v1 = NULL; dvander@11: S *v2 = NULL; dvander@11: v1 = v2; dvander@11: (void)v1; dvander@11: #endif dvander@11: } dvander@28: }; dvander@28: dvander@11: template dvander@11: class Local dvander@11: { dvander@11: friend class Zone; dvander@11: dvander@11: Zone *zone_; dvander@28: T *thing_; dvander@11: Local *prev_; dvander@11: dvander@11: Local *prev() { dvander@11: return prev_; dvander@11: } dvander@11: Local *toRaw() { dvander@11: return reinterpret_cast*>(this); dvander@11: } dvander@11: dvander@11: public: dvander@29: // These are implemented in Zone.h. dvander@28: inline explicit Local(Zone *zone, T *thing = NULL); dvander@11: inline ~Local(); dvander@11: dvander@11: const Local &operator =(T *thing) { dvander@11: thing_ = thing; dvander@11: return *this; dvander@11: } dvander@11: T *operator ->() const { dvander@11: return operator *(); dvander@11: } dvander@11: T *operator *() const { dvander@11: return thing_; dvander@11: } dvander@11: operator bool () const { dvander@11: return !!thing_; dvander@11: } dvander@83: bool operator !=(const Local &other) { dvander@83: return thing_ != other.thing_; dvander@83: } dvander@11: dvander@174: T **address() { dvander@174: return (T **)&thing_; dvander@11: } dvander@174: T * const *address() const { dvander@174: return (T * const *)&thing_; dvander@11: } dvander@54: T **ref() { dvander@54: return &thing_; dvander@54: } dvander@11: operator T *() { dvander@11: return thing_; dvander@11: } dvander@11: dvander@191: Local &operator =(const Local &other) { dvander@191: thing_ = other.thing_; dvander@191: return *this; dvander@191: } dvander@191: dvander@11: private: dvander@11: // Disallow heap allocation. dvander@11: void *operator new(size_t size); dvander@11: void *operator new[](size_t size); dvander@11: dvander@11: // Disallow copy construction. dvander@11: Local(const Local &other); dvander@28: }; dvander@28: dvander@27: // A ScopedRoot is a special kind of handle for storing references on the dvander@27: // heap in bulk. dvander@27: template dvander@27: class ScopedRoot dvander@27: { dvander@29: T **thingp_; dvander@27: dvander@27: private: dvander@29: // This is implemented in Zone.h. dvander@29: inline T **make(T *other); dvander@29: dvander@29: void assign(T *other) { dvander@34: *thingp_ = other; dvander@27: } dvander@27: dvander@27: public: dvander@53: ScopedRoot(); dvander@29: dvander@29: // This is implemented in Zone.h. dvander@29: inline ScopedRoot(T *thing); dvander@29: dvander@27: ScopedRoot &operator =(const ScopedRoot &other) { dvander@27: assign(*other); dvander@27: return *this; dvander@27: } dvander@29: ScopedRoot &operator =(T *other) { dvander@27: assign(other); dvander@27: return *this; dvander@27: } dvander@27: T *operator ->() const { dvander@27: return operator *(); dvander@27: } dvander@27: T *operator *() const { dvander@29: return *thingp_; dvander@29: } dvander@29: operator T *() const { dvander@34: return *thingp_; dvander@27: } dvander@27: operator bool () const { dvander@53: return !!*thingp_; dvander@34: } dvander@34: T **address() const { dvander@34: return thingp_; dvander@27: } dvander@28: }; dvander@28: dvander@11: template template inline dvander@11: Handle::Handle(const Local &local) dvander@11: { dvander@11: typeCheck(); dvander@34: thingp_ = reinterpret_cast(local.address()); dvander@34: } dvander@34: dvander@34: template template inline dvander@34: Handle::Handle(const ScopedRoot &root) dvander@34: { dvander@34: typeCheck(); dvander@34: thingp_ = reinterpret_cast(root.address()); dvander@28: } dvander@28: dvander@28: } dvander@28: dvander@28: #endif // _include_jitcraft_rooting_h_