Skip to content

Borland RAII Tools

DryPerspective edited this page Oct 4, 2023 · 1 revision

A small collection of tools which exploit RAII pattern to perform automatic cleanup on any exit of a scope, be it by returning normally or by an exception being thrown. These allow for much simpler code with minimal need for boilerplate - rather than needing to catch any possible exception and make sure things are dealt with manually before rethrowing, work is always done automatically. Note that these tools are written such that access to the underlying object can be performed through the RAII object (though this is not required). That is to say that if you create a raii::query object qry, you can manipulate the underlying TADOQuery via qry->SQL->Add("SELECT ..."); just as you can through the raw query itself via DMod->ADOQueryWhatever->SQL->Add("SELECT...");

Note that these tools take temporary, weak ownership of the surrounding resource. They are not smart pointers in that they will not delete or destroy their pointed-to object when they are destroyed. They are intended to be used alongside the typical C++Builder pattern of global singletons with static lifetime; where a lack of management of resources typically means that one function exiting unexpectedly can leave the program's global state in an inconsistent or unexpected state when the next function attempt to use it.

The tools in this header exist in nested namespace dp::raii.

List of Features

disabler A tool to automatically disable some TControl object until the end of the current scope
cursor A tool to set the screen cursor to a given value, and automatically reset it afterwards
query A tool to automatically close and clear a TADOQuery object on scope exit
connection A tool which will automatically roll back any transaction on a TADOConnection object if exiting unexpectedly

Sample Code

#include "borland/borland_raii.h"

int some_function(){
    //Set the cursor to an hourglass for this function and automatically reset to what it was before when the function ends
    dp::raii::cursor SetCursorLoading(crHourGlass); 

    //Create a RAII query object
    dp::raii::query qry(DMod->ADOFooQuery);
    qry->SQL->Add(L"SELECT * FROM Foo WHERE Bar");
    qry->Open();
    if(qry->IsEmpty()){
        throw Exception("Empty table"); //Query automatically closed and cleared, cursor set back to what it was before
    }

    ShowMessage("Found a result");
    //Note that instead of qry->whatever we could equally have done DMod->ADOFooQuery->whatever and the result would be the same
    return DMod->ADOFooQuery->FieldByName("baz")->AsInteger;

} //Query automatically closed and cleared, cursor set back to what it was before  

Clone this wiki locally