| … | … | @@ -14,11 +14,6 @@ |
| 14 | 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 15 | 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 16 | 16 | * GNU General Public License for more details. |
| 17 | * | |
| 18 | * You should have received a copy of the GNU Affero General Public License | |
| 19 | * along with this program; if not, write to: | |
| 20 | * Free Software Foundation, Inc., | |
| 21 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | |
| 22 | 17 | */ |
| 23 | 18 | |
| 24 | 19 | #include <string> |
| … | … | @@ -42,6 +37,115 @@ using namespace opencog; |
| 42 | 37 | |
| 43 | 38 | // ==================================================================== |
| 44 | 39 | |
| 40 | void AtomSpace::init(void) | |
| 41 | { | |
| 42 | // Timestamp provides the primary ID, which the user might | |
| 43 | // over-write with a given name. Normally, the timestamp is | |
| 44 | // (almost) enough to provide a distinct, unique name... | |
| 45 | // expect in cases of extreme multi-threading, when multiple | |
| 46 | // thread can end up with the same timestamp, even at the | |
| 47 | // nanosecond level, dependong on the OS, scheduling, interrupts, | |
| 48 | // etc. So we further disambiguate (DAB) with a per-session counter. | |
| 49 | static std::atomic_uint64_t dabcnt(1); | |
| 50 | ||
| 51 | struct timespec ts; | |
| 52 | clock_gettime(CLOCK_REALTIME, &ts); | |
| 53 | char buf[64]; | |
| 54 | strftime(buf, sizeof(buf), "/%Y-%m-%d %H:%M:%S", gmtime(&ts.tv_sec)); | |
| 55 | sprintf(buf + strlen(buf), ".%09ld/%ld", ts.tv_nsec, dabcnt.fetch_add(1)); | |
| 56 | ||
| 57 | _name = buf; | |
| 58 | ||
| 59 | // Connect signal to find out about type additions | |
| 60 | addedTypeConnection = | |
| 61 | _nameserver.typeAddedSignal().connect( | |
| 62 | &AtomSpace::typeAdded, this); | |
| 63 | } | |
| 64 | ||
| 65 | /** | |
| 66 | * Transient atomspaces are intended for use as scratch spaces, to hold | |
| 67 | * temporary results during evaluation, pattern matching and inference. | |
| 68 | */ | |
| 69 | AtomSpace::AtomSpace(AtomSpace* parent, bool transient) : | |
| 70 | Frame(ATOM_SPACE), | |
| 71 | _read_only(false), | |
| 72 | _copy_on_write(transient), | |
| 73 | _nameserver(nameserver()), | |
| 74 | addedTypeConnection(0) | |
| 75 | { | |
| 76 | if (parent) { | |
| 77 | // Set the COW flag by default, for any Atomspace that sits on | |
| 78 | // top of another one. This provides a "common-sense" behavior | |
| 79 | // that most users would expect. | |
| 80 | _copy_on_write = true; | |
| 81 | _environ.push_back(AtomSpaceCast(parent)); | |
| 82 | _outgoing.push_back(HandleCast(parent)); | |
| 83 | } | |
| 84 | init(); | |
| 85 | } | |
| 86 | ||
| 87 | AtomSpace::AtomSpace(const AtomSpacePtr& parent) : | |
| 88 | Frame(ATOM_SPACE), | |
| 89 | _read_only(false), | |
| 90 | _copy_on_write(false), | |
| 91 | _nameserver(nameserver()), | |
| 92 | addedTypeConnection(0) | |
| 93 | { | |
| 94 | if (nullptr != parent) { | |
| 95 | // Set the COW flag by default; it seems like a simpler | |
| 96 | // default than setting it to be write-through. | |
| 97 | _copy_on_write = true; | |
| 98 | _environ.push_back(parent); | |
| 99 | _outgoing.push_back(HandleCast(parent)); | |
| 100 | } | |
| 101 | ||
| 102 | init(); | |
| 103 | } | |
| 104 | ||
| 105 | AtomSpace::AtomSpace(const HandleSeq& bases) : | |
| 106 | Frame(ATOM_SPACE, bases), | |
| 107 | _read_only(false), | |
| 108 | _copy_on_write(false), | |
| 109 | _nameserver(nameserver()), | |
| 110 | addedTypeConnection(0) | |
| 111 | { | |
| 112 | for (const Handle& base : bases) | |
| 113 | { | |
| 114 | if (_nameserver.isA(base->get_type(), ATOM_SPACE)) | |
| 115 | { | |
| 116 | _environ.push_back(AtomSpaceCast(base)); | |
| 117 | continue; | |
| 118 | } | |
| 119 | if (base->is_executable()) | |
| 120 | { | |
| 121 | ValuePtr vp(base->execute()); | |
| 122 | AtomSpacePtr as(AtomSpaceCast(vp)); | |
| 123 | if (nullptr == as) | |
| 124 | throw RuntimeException(TRACE_INFO, | |
| 125 | "AtomSpace - executable base not an AtomSpace! Got %s", | |
| 126 | vp->to_string().c_str()); | |
| 127 | _environ.push_back(as); | |
| 128 | continue; | |
| 129 | } | |
| 130 | ||
| 131 | throw RuntimeException(TRACE_INFO, | |
| 132 | "AtomSpace - bases must be AtomSpaces! Got %s", | |
| 133 | base->to_string().c_str()); | |
| 134 | } | |
| 135 | ||
| 136 | if (0 < bases.size()) _copy_on_write = true; | |
| 137 | init(); | |
| 138 | } | |
| 139 | ||
| 140 | ||
| 141 | AtomSpace::~AtomSpace() | |
| 142 | { | |
| 143 | _nameserver.typeAddedSignal().disconnect(addedTypeConnection); | |
| 144 | clear_all_atoms(); | |
| 145 | } | |
| 146 | ||
| 147 | // ==================================================================== | |
| 148 | ||
| 45 | 149 | // An extremely primitive permissions system. |
| 46 | 150 | void AtomSpace::set_read_only(void) |
| 47 | 151 | { |
| … | … | @@ -19,11 +19,6 @@ |
| 19 | 19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 20 | 20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 21 | 21 | * GNU General Public License for more details. |
| 22 | * | |
| 23 | * You should have received a copy of the GNU Affero General Public License | |
| 24 | * along with this program; if not, write to: | |
| 25 | * Free Software Foundation, Inc., | |
| 26 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | |
| 27 | 22 | */ |
| 28 | 23 | |
| 29 | 24 | #include "AtomSpace.h" |
| … | … | @@ -49,113 +44,6 @@ using namespace opencog; |
| 49 | 44 | |
| 50 | 45 | // ==================================================================== |
| 51 | 46 | |
| 52 | void AtomSpace::init(void) | |
| 53 | { | |
| 54 | // Timestamp provides the primary ID, which the user might | |
| 55 | // over-write with a given name. Normally, the timestamp is | |
| 56 | // (almost) enough to provide a distinct, unique name... | |
| 57 | // expect in cases of extreme multi-threading, when multiple | |
| 58 | // thread can end up with the same timestamp, even at the | |
| 59 | // nanosecond level, dependong on the OS, scheduling, interrupts, | |
| 60 | // etc. So we further disambiguate (DAB) with a per-session counter. | |
| 61 | static std::atomic_uint64_t dabcnt(1); | |
| 62 | ||
| 63 | struct timespec ts; | |
| 64 | clock_gettime(CLOCK_REALTIME, &ts); | |
| 65 | char buf[64]; | |
| 66 | strftime(buf, sizeof(buf), "/%Y-%m-%d %H:%M:%S", gmtime(&ts.tv_sec)); | |
| 67 | sprintf(buf + strlen(buf), ".%09ld/%ld", ts.tv_nsec, dabcnt.fetch_add(1)); | |
| 68 | ||
| 69 | _name = buf; | |
| 70 | ||
| 71 | // Connect signal to find out about type additions | |
| 72 | addedTypeConnection = | |
| 73 | _nameserver.typeAddedSignal().connect( | |
| 74 | &AtomSpace::typeAdded, this); | |
| 75 | } | |
| 76 | ||
| 77 | /** | |
| 78 | * Transient atomspaces are intended for use as scratch spaces, to hold | |
| 79 | * temporary results during evaluation, pattern matching and inference. | |
| 80 | */ | |
| 81 | AtomSpace::AtomSpace(AtomSpace* parent, bool transient) : | |
| 82 | Frame(ATOM_SPACE), | |
| 83 | _read_only(false), | |
| 84 | _copy_on_write(transient), | |
| 85 | _nameserver(nameserver()), | |
| 86 | addedTypeConnection(0) | |
| 87 | { | |
| 88 | if (parent) { | |
| 89 | // Set the COW flag by default, for any Atomspace that sits on | |
| 90 | // top of another one. This provides a "common-sense" behavior | |
| 91 | // that most users would expect. | |
| 92 | _copy_on_write = true; | |
| 93 | _environ.push_back(AtomSpaceCast(parent)); | |
| 94 | _outgoing.push_back(HandleCast(parent)); | |
| 95 | } | |
| 96 | init(); | |
| 97 | } | |
| 98 | ||
| 99 | AtomSpace::AtomSpace(const AtomSpacePtr& parent) : | |
| 100 | Frame(ATOM_SPACE), | |
| 101 | _read_only(false), | |
| 102 | _copy_on_write(false), | |
| 103 | _nameserver(nameserver()), | |
| 104 | addedTypeConnection(0) | |
| 105 | { | |
| 106 | if (nullptr != parent) { | |
| 107 | // Set the COW flag by default; it seems like a simpler | |
| 108 | // default than setting it to be write-through. | |
| 109 | _copy_on_write = true; | |
| 110 | _environ.push_back(parent); | |
| 111 | _outgoing.push_back(HandleCast(parent)); | |
| 112 | } | |
| 113 | ||
| 114 | init(); | |
| 115 | } | |
| 116 | ||
| 117 | AtomSpace::AtomSpace(const HandleSeq& bases) : | |
| 118 | Frame(ATOM_SPACE, bases), | |
| 119 | _read_only(false), | |
| 120 | _copy_on_write(false), | |
| 121 | _nameserver(nameserver()), | |
| 122 | addedTypeConnection(0) | |
| 123 | { | |
| 124 | for (const Handle& base : bases) | |
| 125 | { | |
| 126 | if (_nameserver.isA(base->get_type(), ATOM_SPACE)) | |
| 127 | { | |
| 128 | _environ.push_back(AtomSpaceCast(base)); | |
| 129 | continue; | |
| 130 | } | |
| 131 | if (base->is_executable()) | |
| 132 | { | |
| 133 | ValuePtr vp(base->execute()); | |
| 134 | AtomSpacePtr as(AtomSpaceCast(vp)); | |
| 135 | if (nullptr == as) | |
| 136 | throw RuntimeException(TRACE_INFO, | |
| 137 | "AtomSpace - executable base not an AtomSpace! Got %s", | |
| 138 | vp->to_string().c_str()); | |
| 139 | _environ.push_back(as); | |
| 140 | continue; | |
| 141 | } | |
| 142 | ||
| 143 | throw RuntimeException(TRACE_INFO, | |
| 144 | "AtomSpace - bases must be AtomSpaces! Got %s", | |
| 145 | base->to_string().c_str()); | |
| 146 | } | |
| 147 | ||
| 148 | if (0 < bases.size()) _copy_on_write = true; | |
| 149 | init(); | |
| 150 | } | |
| 151 | ||
| 152 | ||
| 153 | AtomSpace::~AtomSpace() | |
| 154 | { | |
| 155 | _nameserver.typeAddedSignal().disconnect(addedTypeConnection); | |
| 156 | clear_all_atoms(); | |
| 157 | } | |
| 158 | ||
| 159 | 47 | void AtomSpace::clear_all_atoms() |
| 160 | 48 | { |
| 161 | 49 | #if USE_INCOME_INDEX |