defer test

Bare metal programming in PureBasic, for experienced users
User avatar
chi
Addict
Addict
Posts: 1087
Joined: Sat May 05, 2007 5:31 pm
Location: Austria

defer test

Post by chi »

Found this defer macro and played around a little bit. It's very restricted (in PB), cumbersome and verbose (.c file), but somehow works...

Code: Select all

CompilerIf #PB_Compiler_Backend <> #PB_Backend_C  
  CompilerError "'defer test' needs the C backend (GCC only)"
CompilerEndIf

Macro defer_Pb(func)
! #undef CAT_
! #undef CAT
! #undef defer

! #define CAT_(a, b) a ## b
! #define CAT(a, b) CAT_(a, b)

! #define defer                                                                               \
!     auto void CAT(DEFER_FUNCTION_, __LINE__)(int *);                                        \
!     int CAT(DEFER_VAR_, __LINE__) __attribute__((cleanup(CAT(DEFER_FUNCTION_, __LINE__)))); \
!     void CAT(DEFER_FUNCTION_, __LINE__)(int *)  

! defer { PB_#func; }
EndMacro

Macro defer_My(func)
! #undef CAT_
! #undef CAT
! #undef defer

! #define CAT_(a, b) a ## b
! #define CAT(a, b) CAT_(a, b)

! #define defer                                                                               \
!     auto void CAT(DEFER_FUNCTION_, __LINE__)(int *);                                        \
!     int CAT(DEFER_VAR_, __LINE__) __attribute__((cleanup(CAT(DEFER_FUNCTION_, __LINE__)))); \
!     void CAT(DEFER_FUNCTION_, __LINE__)(int *)  

! defer { f_#func; }
EndMacro

Procedure My_Print(txt$)
  PrintN(txt$)
EndProcedure

Procedure Run()
  defer_Pb(PrintN(L"\npress any key to continue..."))     ;;; L"" needed to output wide-character strings 
  My_Print(~"defer test:\n")                              ;;; if ommited, calling next line: defer_My(my_print(..)) = unresolved external symbol
  defer_My(my_print(L"\nexpected output: 1, 3, 4, 6, 5, 2")) ;;; my_print must be lower case...
  
  PrintN(" 1 ")  
  defer_Pb(PrintN(L" 2 "))
  PrintN(" 3 ")  
  PrintN(" 4 ")
  defer_Pb(PrintN(L" 5 ")) 
  PrintN(" 6 ") 
EndProcedure

OpenConsole()
defer_My(my_print(L"not working in PB's main scope"))
Run()
Input()
Et cetera is my worst enemy
User avatar
NicTheQuick
Addict
Addict
Posts: 1514
Joined: Sun Jun 22, 2003 7:43 pm
Location: Germany, Saarbrücken
Contact:

Re: defer test

Post by NicTheQuick »

Can you please explain what this actually does?
The english grammar is freeware, you can use it freely - But it's not Open Source, i.e. you can not change it or publish it in altered way.
User avatar
spikey
Enthusiast
Enthusiast
Posts: 761
Joined: Wed Sep 22, 2010 1:17 pm
Location: United Kingdom

Re: defer test

Post by spikey »

Some languages, like Go, define a defer function which allows an operation to be stated at one point in code but defers the execution of said operation until the enclosing procedure ends. The idea is to protect against something like this:

Code: Select all

Procedure Something()
  *Buffer = AllocateMemory(2000)
  
  ; do something complicated with memory
  ; ...
  If Complicated Code doesn't work 
    ProcedureReturn
  Else
    ; do something else here.
  EndIf
  
  FreeMemory(*Buffer)  
  
EndProcedure
In this case, if "Complicated Code" doesn't work the procedure returns without freeing the memory, leading to a leak.

In these languages, you can write something similar to:

Code: Select all

Procedure Something()
  *Buffer = AllocateMemory(2000)
  Defer(FreeMemory(*Buffer))
  
  ; do something complicated with memory
  ; ...
  If Complicated Code doesn't work 
    ProcedureReturn
  Else
    ; do something else here.
  EndIf
  
EndProcedure
The compiler will automatically handle deferred operations regardless of where they appeared in the source and the actual exit point in the procedure. The theory says it should lead to fewer bugs because allocation and deallocation code can always be adjacent in the source code but effective at the exit point in the object code. There is less likelihood of something being forgotten by a fallible programmer or a future code change breaking something accidentally because something was overlooked.

There is a more comprehensive explanation at https://www.digitalocean.com/community/ ... efer-in-go.
User avatar
jacdelad
Addict
Addict
Posts: 2001
Joined: Wed Feb 03, 2021 12:46 pm
Location: Riesa

Re: defer test

Post by jacdelad »

Like a Try...Error...Finally?
Good morning, that's a nice tnetennba!

PureBasic 6.21/Windows 11 x64/Ryzen 7900X/32GB RAM/3TB SSD
Synology DS1821+/DX517, 130.9TB+50.8TB+2TB SSD
User avatar
chi
Addict
Addict
Posts: 1087
Joined: Sat May 05, 2007 5:31 pm
Location: Austria

Re: defer test

Post by chi »

spikey already nailed it with the description... thx ;)
Et cetera is my worst enemy
User avatar
NicTheQuick
Addict
Addict
Posts: 1514
Joined: Sun Jun 22, 2003 7:43 pm
Location: Germany, Saarbrücken
Contact:

Re: defer test

Post by NicTheQuick »

Thanks for the clarification. That sounds really cool.

I am however a big fan of proper exception handling. A try..catch..finally construct would be much appreciated but I fear Purebasic will never get this functionality.
The english grammar is freeware, you can use it freely - But it's not Open Source, i.e. you can not change it or publish it in altered way.
User avatar
fsw
Addict
Addict
Posts: 1603
Joined: Tue Apr 29, 2003 9:18 pm
Location: North by Northwest

Re: defer test

Post by fsw »

Some other languages offera defer that is executed when a scope ends (any scope, not only procedures).

I am to provide the public with beneficial shocks.
Alfred Hitshock
Post Reply