Defined() as Local Scope Destructor

Share your advanced PureBasic knowledge/code with the community.
User avatar
grabiller
Enthusiast
Enthusiast
Posts: 309
Joined: Wed Jun 01, 2011 9:38 am
Location: France - 89220 Rogny-Les-Septs-Ecluses
Contact:

Defined() as Local Scope Destructor

Post by grabiller »

Hi,

For the project I'm currently working on, I've found a very useful way to use the PureBasic compiler function 'Defined()'.

I wanted to share that with you, perhaps this will give you other ideas as well to use this very powerful feature of PureBasic.

For my project I've implemented a hierarchical logging system. Basically it allows to have a hierarchical view of which classes/procedures have been visited and from exactly where each log message has been produced and in which context.

Normally, to implement this in C++, you use a simple local object on the stack. When it is created (constructor called) it send a 'Log.Enter()' signal/message/call to the logging system, and when this object leave the scope of the procedure, the destructor is called and send a 'Log.Leave()' signal/message/call to the logging system. In between you use this object to log messages.

This is pretty automatic, you don't have to worry about the life time of this local object nor it's hierarchical nature/management.

In C, you have to do this manually whenever you leave your procedure. At each 'exit point' of your procedure you have to call for 'Log_Leave()'.

In PureBasic you have to do the same. But, thanks to this Defined() compiler function, you can bring back the automatic management of 'scope destructor' with the help of some macros too.

Code: Select all

Procedure.i MyProc()
  
  LOG_ENTER()
  
  Protected my_result.i = 0
  
  ; ../..
  
  ret( my_result )

EndProcedure
Here LOG_ENTER() is a Macro that define a local variable and automatically call for 'LogEnter()'. (in the actual implementation these macro and procedure also have arguments to define the 'area' and 'class/procedure' of this part of the code).

Then the ret() macro is defined this way:

Code: Select all

Macro ret( r )
  CompilerIf Defined( log_args, #PB_Variable )
    LogLeave()  
  CompilerEndIf
  ProcedureReturn r
EndMacro
'log_args' is a local variable used by the other logging macros to post messages, and 'LogLeave()' is then the logging system procedure that need to be called whenever the code exit the Procedure.

Thanks to the PureBasic 'Defined()' compiler function, I don't have to think about this anymore, it will automatically call for 'LogLeave()' whenever I exit a procedure and this, only if it 'detects' the use of the logging system through the definition of the specific local variable used by this system.

On a side note it also work for Procedures that return nothing, I use a ret( void ) macro for this, 'void' being defined as nothing.

This is very practical and in my case it simulates the automatic C++ scope destructor of local objects.
guy rabiller | radfac founder / ceo | raafal.org
BorisTheOld
Enthusiast
Enthusiast
Posts: 542
Joined: Tue Apr 24, 2012 5:08 pm
Location: Ontario, Canada

Re: Defined() as Local Scope Destructor

Post by BorisTheOld »

Good idea!

I'm a big fan of macros. It's an easy way of expanding the vocabulary of a programming language. They also simplify code and reduce the chance of coding errors.
For ten years Caesar ruled with an iron hand, then with a wooden foot, and finally with a piece of string.
~ Spike Milligan
Post Reply