Does Delphi have any equivalent to C's volatile variable?

≯℡__Kan透↙ 提交于 2019-11-29 03:42:47

Short answer: no.

However, I am not aware of any situation in which the conservative approach of the compiler will change the number of reads or writes if you follow this approach:

When reading a cross-thread visible location, save its value to a local before doing any further manipulation; similarly, restrict writes to a single assignment.

The Delphi compiler does not perform common subexpression elimination (CSE) on non-local location expressions when there are calls to non-inlined methods between the expressions, as the compiler doesn't do interprocedural optimization and thus it would not be correct even for single-threaded code.

So, you may want to use InterlockedExchange() to do your reads and writes to force this; additionally, this will cause a full memory barrier, so the processor won't reorder reads and writes either.

According to The Delphi Language for Mobile Development whitepaper, Delphi's mobile compilers have supported a [volatile] attribute since they were first introduced:

The volatile attribute is used to mark fields that are subject to change by different threads, so that code generation does not optimize copying the value in a register or another temporary memory location.

You can use the volatile attribute to mark the following declarations:

  • Variables (global and local)
  • Parameters
  • Fields of a record or a class.

You cannot use the volatile attribute to mark the following declarations:

  • Type
  • Procedures, Functions or Methods
  • Expressions

type
  TMyClass = class
  private
    [volatile] FMyVariable: TMyType;
  end;

Starting with Delphi 10.1 Berlin, the desktop compilers now support [volatile] as well.

Attributes Supported by All Compilers

Now, all Delphi compilers support the following attributes:

I don't know of any equivalent, nor do I think that the absolute directive will help you. absolute allows you to have two variables that use the same address, but I do not think it will prevent the compiler from optimising references to that memory.

I imagine you could use a pointer and manage it yourself. That way whatever the compiler does as far as optimising retrival of the pointer value, it should not assume the value stored at the address is the same as last time it read it, but this is pure speculation.

Delphi for .Net does not have the keyword either, but the .Net platform has util functions for it. See Thread.VolatileRead and Thread.VolatileWrite.

Use dynamically allocated pointers?

var
  MyVarPtr: ^integer;
begin
  New(MyVarPtr);
  MyVarPtr^ := 5;
...

This should keep the compiler from using a register for the integer value (but it might still use one for the address). I am not sure how that compares to volatile, though.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!