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

1.6.8 Blobs
All Application Manual Name SummaryHelp

  • Documentation
    • Reference manual
    • Packages
      • A C++ interface to SWI-Prolog
        • A C++ interface to SWI-Prolog
          • Overview
            • Blobs
              • A review of C++ features used by the API
              • How to define a blob using C++
              • The life of a PlBlob
              • C++ exceptions and blobs
              • Sample PlBlob code (connection to database)
              • Discussion of the sample PlBlob code
              • Sample PlBlob code (wrapping a pointer)
              • Discussion of the sample PlBlob code (wrapping a pointer)
              • Identifying blobs by atoms

1.6.8.4 C++ exceptions and blobs

When a blob is used in the context of a PREDICATE() macro, it can raise a C++ exception (PlFail or PlException) and the PREDICATE() code will convert the exception to the appropriate Prolog failure or error; memory allocation exceptions are also handled.

Blobs have callbacks, which can run outside the context of a PREDICATE(). Their exception handling is as follows:

void PlBlob::acquire()
, which is called from PlBlobV<MyBlob>::acquire(), can throw a C++ exception. The programmer cannot override this.
int PlBlob::compare_fields(const PlBlob *_b)
, which is called from PlBlobV<MyBlob>::compare(), should not throw an exception. A Prolog error won't work as it uses “raw pointers” and thus a GC or stack shift triggered by creating the exception will upset the system.
bool PlBlob::write_fields(IOStream *s, int flags)
, which is called from PlBlobV<MyBlob>::write(), can throw an exception, just like code inside a PREDICATE(). In particular, you can wrap calls to Sfprintf() in PlCheckFail(), although the calling context will check for errors on the stream, so checking the Sfprintf() result isn't necessary.
void PlBlob::PlBlob::save(IOStream *fd)
can throw a C++ exception, including PlFail().
PlAtom PlBlob::PlBlob::load(IOSTREAM *fd)
can throw a C++ exception, which is converted to a return value of PlAtom::null, which is interpreted by Prolog as failure.
bool PlBlob::PlBlob::pre_delete()
, which is called from PlBLobV<MyBLOB>::release(), can return false (or throw a PlException or PlExceptinFailBase, which will be interpreted as a return value of false), resulting in the blob not being garbage collected, and the destructor not being called. Note that this doesn't work well with final clean-up atom garbage collection, which disregards the return value and also doesn't respect the ordering of blob dependencies (e.g., if an iterator blob refers to a file-like blob, the file-like blob might be deleted before the iterator is deleted).

This code runs in the gc thread. The only PL_*() function that can safely be called are PL_unregister_atom() (which is what PlAtom::unregister_ref() calls).

ClioPatria (version V3.1.1-51-ga0b30a5)