• Places
    • Home
    • Graphs
    • Prefixes
  • Admin
    • Users
    • Settings
    • Plugins
    • Statistics
  • Repository
    • Load local file
    • Load from HTTP
    • Load from library
    • Remove triples
    • Clear repository
  • Query
    • YASGUI SPARQL Editor
    • Simple Form
  • Help
    • Documentation
    • Tutorial
    • Roadmap
    • HTTP Services
  • Login

2.5.6 Blobs
All Application Manual Name SummaryHelp

  • Documentation
    • Reference manual
    • Packages
      • A C++ interface to SWI-Prolog
        • A C++ interface to SWI-Prolog (Version 2)
          • Overview (version 2)
            • Blobs
              • How to define a blob using C++
              • The life of a PlBlob
              • C++ exceptions and blobs
              • Sample PlBlob code
              • Discussion of the sample PlBlob code
              • Identifying blobs by atoms

2.5.6.2 The life of a PlBlob

In this section, the blob is of type MyBlob, a subclass of PlBlob.

A blob is typically created by calling a predicate that does the following:

  • Creates the blob using auto ref = std::unique_ptr<PlBlob>(new MyBlob>(...)) (std::make_unique() can't be used because it returns type std::unique_ptr<MyBlob> but PlTerm::unify_blob() requires a std::unique_ptr<PlBlob> and C++'s type inferencing can't figure out that this is a covariant type).

  • Calls PlTerm::unify_blob(ref), using PlCheckFail() to throw an exception if it fails. This, in turn, calls:
    • PlBlobV<MyBlob>acquire(), which calls
    • MyBlob::acquire(), which sets MyBlob::symbol_ (MyBlob::symbol_ is usually accessed using the method MyBlob::symbol_term()). If this all succeeds, PlTerm::unify_blob(ref) calls ref.release() to pass ownership to the Prolog blob. If you wish to use std::make_unique<MyBlob>(), you could instead do:
            auto ref = std::make_unique<MyBlob>(...);
               ... // code that accesses fields in *ref
            std::unique_ptr<PlBlob> refb(ref.release()); // transfer ownership of ptr
               // from here on, can't access fields in *ref
            return A2.unify_blob(refb);
            

At this point, the blob is owned by Prolog and will be freed by its atom garbage collector, which will call the blob's destructor.

Whenever a predicate is called with the blob as an argument (e.g., as A1), the blob can be accessed by PlBlobv<MyBlob>::cast_check(A1.as_atom()).

Within a method, the Prolog blob can be accessed as a term (e.g., for constructing an error term) using the method MyBlob::symbol_term(). This field is initialized by the call to PlTerm::unify_blob(); if MyBlob::symbol_term() is called before a successful call to PlTerm::unify_blob(), MyBlob::symbol_term() returns a PlTerm_var.

When the atom garbage collector runs, it frees the blob by first calling the release() callback, which does delete, which calls the destructor MyBlob:: MyBlob(). Note that C++ destructors are not supposed to raise exception; they also should not cause a Prolog error, which could cause deadlock unless the real work is done in another thread.

Often it is desired to release the resources before the garbage collector runs. To do this, the programmer can provide a "close" predicate which is the inverse of the "open" predicate that created the blob. This typically has the same logic as the destructor, except that it can raise a Prolog error.

ClioPatria (version V3.1.1-48-gf653ce4)