Thursday, October 8, 2009

Delphi check-in log entries of the day:

25232 trunk/com/ scanner.c Thu Oct 8 20:41:10 2009 UTC ytagawa

Log:

[dcc64]
(scanner.c) Don't define ASSEMBLER for x64 for awhile.



25224 trunk/com/ codegen.c Thu Oct 8 12:35:00 2009 UTC eboling

Log:

Refactoring in PassParams to support changes to stack alignment code.
Changed the logic for aligning the stack for parameter lists for the Mac.


I’ll just leave that little tidbit for you all to chew on for a now. I’ve seen a lot of rampant speculation and and angst surrounding the release of the current roadmap. Maybe this will at least demonstrate that, yes, things are moving forward and people are actually working on interesting things.


DISCLAIMER: If you read into this more that what is actually in this post and begin ranting an raving about how this or that thing should be done one way or another, I may simply delete your comment. Remember there are no promises or anything of any value in this post. If you make a business decision based any information contained herein, then I’d really like to play you in a round of Texas Hold’em… you’d be easy prey and I’ll be happy to take all your money, and I’m not even that good.

Friday, September 4, 2009

What happened to version 13?

During the RAD Studio 2010 field test and now out in the Delphi non-tech newsgroups, there had been a lot of discussion, speculation and even some angst about the mysterious lack of version 13. Chill folks. The story is simple with no real conspiracies involved. In fact, the only conspiracy involved was that we knew from the outset that it would spark discussion and conspiracies.

After each product release there is a period of time where the internal developer builds overlap with the released product and the next release. This can cause confusion among the team and phantom errors if a developer build were to ever meet up with a released build. To limit this overlap, we try and bump the version number as early in the next release cycle as possible. The scene went like this:

Rewind to September 24th of 2008. I’m sitting at my desk reading emails, writing emails, surfing the interwebs, waiting for a build to complete, etc… There’s a knock on the door frame of my office (my door is always open). I turn around and Dave Wilhelm is standing there.

“I’m about ready bump the version number.”

“So the next version would be, uh, 13, right?”, I said with a pondering look.

“Yep. And, yes, that’s an interesting number”, Dave said with a wry smirk. A mischievous smile appeared on my face. Dave chuckled. Then he added, “I think we have two choices here. We can defiantly embrace it, or just skip it. What does our release schedule look like next year?”

“Why?”

“If we were to release in October, having a version 13 would be clearly embracing that whole mystique. You know, Halloween, black cats, zombies, ghouls, yadda yadda…”

I chuckled. “That could be a whole sub theme of the release! However, it looks like we’re slated to release about the same time next year. So that won’t work. We should just skip it. I don’t think there is a Friday the 13th around that time either.”

“I’ll ask a few folks on the team if they have any strong opinions one way or another.”

“Yep. Just like many buildings don’t have a floor 13 and go from floor 12 to 14. It will also be a fun trivia question down the road. Besides, I can see the community going into wild, random speculation and conspiracies as to why did they skip 13.”, I said with a slight smirk and a muted chuckle.

“Exactly. I also understand it is mostly a western superstition. It will certainly be fun to watch all the newsgroups get spun up.”

“Well, we live in the west. We are the ones checking in the changes. So I guess we get to decide.”, I commented defiantly.

“Yep. I’ll check with a few folks and get back to you.”, Dave said as he walked off.

About an hour later, there was another knock on my door. Dave was back.

“The comments among the team ranged from, ‘I don’t care one way or another’ to ‘Sure, go ahead and skip 13’”

“Then it’s decided. Bump it to 14, and check it in. Let the wild, random speculation begin. Explaining this conversation in a blog post will also be fun.”

We both let out a slight chortle and then proceeded to get on with our day.

There you have it. It was a largely unilateral decision. Nothing was ever mentioned about it until fairly deep into the field-test cycle and now after the release it seems to have gotten a decent amount of attention. Psych!

Thursday, September 3, 2009

Class Constructors. Popping the hood.

My last post introduced class constructors and destructors, a new language feature in Delphi 2010. I mainly covered what they were and what kinds of things they’re good for. In this post I’ll cover some of how they’re implemented. I’m sure the question on everyone’s mind is when and how they’re invoked? If you were patient enough to read my entire post, I provided a hint as to the inner workings. The rule for when they run is simple:

    • All eligible class constructors and class destructors are invoked in sequence with unit initialization and finalization, respectively.
    • If a given class constructor or destructor is eligible to be invoked (ie. it was linked into your application), it will run immediately before the initialization section for the unit in which the class is implemented. The class destructors will be invoked immediately after the finalization section for the unit in which the class is implemented.
    • Class constructors in a given unit are generally invoked in the same order of declaration, except in cases described below. Class destructors are invoked in reverse order from the class constructors.
    • For an ancestor class declared in the same unit, its class constructor will be invoked before the descendant class constructor and the class destructor is invoked after the descendant class destructor.
    • If the implementation of given class constructor references another class in the same unit with a class constructor, the referenced class’ class constructor will be invoked before the current class’ class constructor. If the references are cyclic (ie. they reference each other in their class constructors), then they are invoked in reverse order of declaration. This means that there can be cases where a class constructor can reference an “unconstructed” class.
    • Ancestor classes from external units used in the interface section are guaranteed to already have their class constructors run prior to any class constructors on descendant classes within the current unit.
    • Unit cycles can break down the deterministic nature of the above rules in the same manner as unit initialization and finalization. However, for a given unit, it is guaranteed that all the class constructors declared within in it will have already run immediately before the initialization section runs. Congruent to this rule is that it is guaranteed that all the class destructors will run immediately after the finalization section.
    • Dynamically loaded packages, using LoadPackage. Because there is no way to know exactly which classes are going to be used, just like there is no way to know which units are going to be used, all class constructors and destructors along with all unit initialization and finalizations are invoked according to the above rules.

Other rules about their use are:

    • You do not have to declare a class destructor if you declare a class constructor, and vice versa.
    • They cannot be virtual, dynamic or message.
    • They cannot be explicitly called.
    • They cannot have any parameters.
    • They do not have to be called Create and Destroy. (ie. Init and Fini are equally valid names).

With this implementation, it was easier to leverage the same table that the compiler creates for unit initialization and finalization. It satisfies this requirement: “Called automatically to initialize the class before the first instance is created or any static members are referenced.” Issues with cycles are also clearly warned against in VB.NET and C#: “Avoid circular references in Shared … since it is generally impossible to determine the order in which classes containing such references are loaded.”

Another benefit is that since it is running during the initialization/finalization phases, any threading implications are no different than the existing rules regarding unit initialization and finalization.

Class (, Static, or Shared) Constructors (and Destructors)

In my last post, I hinted at a new native Delphi language feature, class constructors and destructors. For those familiar with, say, C# or VB.NET, they are called a ‘static’ constructor (C#), or a ‘shared’ constructor (VB.NET). Let’s now take a closer look at them in terms of how they’re useful along with a little hint at how they’re implemented. Class constructors had been available in Delphi Prism, but until Delphi 2010, they were notably absent from native Delphi. The main reason for this was that the .NET runtime controlled and defined when a ‘static’ or ‘shared’ constructor was invoked. In native Delphi there was no defined mechanism to do the same.

From the C# documentation:

Called automatically to initialize the class before the first instance is created or any static members are referenced. The constructor cannot be called directly.

From the VB.NET documentation:

Shared constructors initialize a type's shared variables; they are run after the program begins executing, but before any references to a member of the type. A shared constructor specifies the Shared modifier, unless it is in a standard module in which case the Shared modifier is implied.

Since the .NET runtime is a garbage-collected environment, there are no references or mention of ‘class destructors’. Because native Delphi is is not garbage collected and requires explicit destruction of instances and freeing of memory, it stood to reason that for congruency, native Delphi would also have the notion of a class destructor.

First of all let’s look at the syntax:

type
EDliException = class(Exception)
private
class constructor Create;
class destructor Destroy;
end;


 


Technically, it does not matter where in the class declaration they are declared (private, public, protected, published) since, as the  documentation above states, “The constructor [destructor (added)] cannot be called directly.” So in this example, I just made them private to merely make it more clear in the source that they cannot be called. Just like the other kinds of ‘class’ methods, the body of theses methods can only access other class methods or variables. They also have no implicit “Self”, so you cannot call virtual class methods in a polymorphic manner. You can have one and only one class constructor/destructor per class type. As we’ll see in a moment, you should treat the class constructor/destructor methods in a manner similar to a unit’s initialization/finalization section. That’s it. It’s pretty simple, really.


Now let’s look at why these are useful. There were several main reasons for adding this to the language. They were:



  1. Improved encapsulation

  2. Better control over smart-linking

  3. Better language compatibility with Delphi-Prism

Improved encapsulation


How many times have you needed to initialize something related to a specific class? What if your class is using the singleton pattern and you need to create that single instance? How about registering the class with a “class-factory?” Prior to Delphi 2010, there were several options available to you, none of which were really in keeping with the OOP notion of encapsulation. You could put all the code into the initialization section of the unit in which the class lived, add a regular class method and call it explicitly, or manually integrate the init code into your application’s startup. By moving all this code into a class constructor, the mere act of “touching” the class will cause the class constructor to run in keeping with the above rules.


Better control over smart-linking


Loosely coupled with improved encapsulation is the notion that by moving any initialization code into the class constructor you have a little more control over what code is linked into your application. You can now take advantage of the fact that as long as the class type isn’t referenced referenced anywhere in your code, none of the code related to the class type is linked in, including the VMT, virtual methods, RTTI, etc.. If you had placed this init code into the initialization section of its containing unit, then at least the VMT, virtual methods and RTTI would have been linked into your application. Even though none of your code references it. The new enhanced RTTI throws an interesting wrinkle to this theory, but that will have to be covered later.


Better language compatibility with Delphi Prism


As Delphi Prism gains popularity, more people will need to maintain some of their code in a manner that they can compile with either compiler. There are still many language constructors that both compilers have that the other doesn’t, but this is a continuing effort to close that gap where it makes sense. Expect to see more work in this area, in both compilers.


In my next post, we’ll “pop the hood” (or bonnet, for our good friends across the pond) and take a peek at how they work and exactly when they are invoked. I will say that many people tend to read way, way too much into this simple statement describing when a class constructor is invoked; “Called automatically to initialize the class before the first instance is created or any static members are referenced.” The only temporal reference in that statement is “…before…”. I will leave you to consider the implications of that word, lest many of you begin to talk about “threading issues” and “code-bloat.” Class constructors and destructors are to classes as initialization and finalization are to units.

Saturday, August 29, 2009

Exceptional Procrastination

I kept putting this post off… ok, ok… that was a really bad pun…

Seems there was a little bit of concern about my last post regarding the new ‘delayed’ directive. Christian Wimmer had a few critiques regarding the implementation and how the exception that was raised was an EExternalException with an obscure exception code. There is a simple explanation for this. The delay load helper functions were taken directly from the C++Builder RTL. By that I mean, the delayhlp.c file gets built to a .obj file by the C++ compiler and then directly linked into the Delphi System unit. There were several key reasons for this. The first of which was the code was already written, has been in many versions of C++Builder RTL (including back in the old Borland C++ days) and has been extensively tested. Another reason is that in order for Delphi and C++Builder to “play-nice,” when a Delphi unit is linked in C++Builder that contains a reference to a delay load import, ILink32 takes over the duties of generating the proper delay load functionality into the PE file. So the C++RTL version of delayhlp.c is what is used. In order to things to remain consistent, this is the route taken. Had there been two delay-load helper functions in the case of a C++Builder application, then any existing C++ code that used the delay load hooks would only work on other C++ code and vice-versa.

Fear not, all is not lost. To satisfy our good friend, Christian’s request, here is a unit that you can use to generate nice, unique Delphi specific exceptions. This is accomplished by leveraging the ability for the delayhlp.c code to be “hooked.” This code also demonstrates another new Delphi language feature, class constructors and destructors. I will describe them in better detail in a subsequent post. If you never reference any of the declared exception types in this unit, the hook is not installed and the normal EExternalException is raised. Presumably you would use this unit for the purpose of actually catching the exceptions and doing something interesting with them. Another thing to note is that you should also be able to add this unit to a C++Builder application and it work for any delay-load functions done in the existing way for C++ and any Delphi units that reference Delphi imports with the delayed directive.

unit DelayExcept;

interface

uses SysUtils;

type
EDliException = class(Exception)
private
class constructor Create;
class destructor Destroy;
end;

EDliLoadLibraryExeception = class(EDliException)
private
FDllName: string;
public
constructor Create(const ADllName: string); overload;

property DllName: string read FDllName;
end;

EDliGetProcAddressException = class(EDliException)
private
FDllName: string;
FExportName: string;
public
constructor Create(const ADllName, AExportName: string); overload;
constructor Create(const ADllName: string; AOrdinal: LongWord); overload;

property DllName: string read FDllName;
property ExportName: string read FExportName;
end;

implementation

{ EDliLoadLibraryExeception }

constructor EDliLoadLibraryExeception.Create(const ADllName: string);
begin
inherited Create(Format('Unable to load ''%s''', [ADllName]));
FDllName := ADllName;
end;

{ EDliGetProcAddressException }

constructor EDliGetProcAddressException.Create(const ADllName, AExportName: string);
begin
inherited Create(Format('Unable to locate export name ''%s'' in ''%s''', [AExportName, ADllName]));
FDllName := ADllName;
FExportName := AExportName;
end;

constructor EDliGetProcAddressException.Create(const ADllName: string;
AOrdinal: LongWord);
begin
inherited Create(Format('Unable to locate export ordinal ''%d'' in ''%s''', [AOrdinal, ADllName]));
FDllName := ADllName;
FExportName := IntToStr(AOrdinal);
end;

function DelayLoadFailureHook(dliNotify: dliNotification; pdli: PDelayLoadInfo): Pointer; stdcall;
begin
Result := nil;
if dliNotify = dliFailLoadLibrary then
raise EDliLoadLibraryExeception.Create(pdli.szDll);
if dliNotify = dliFailGetProcAddress then
if pdli.dlp.fImportByName then
raise EDliGetProcAddressException.Create(pdli.szDll, pdli.dlp.szProcName)
else
raise EDliGetProcAddressException.Create(pdli.szDll, pdli.dlp.dwOrdinal);
end;

{ EDliException }

class constructor EDliException.Create;
begin
SetDliFailureHook(DelayLoadFailureHook);
end;

class destructor EDliException.Destroy;
begin
SetDliFailureHook(nil);
end;

end.

Tuesday, August 25, 2009

Procrastinators Unite… Eventually!

We’re all taught at an early age to “Never put off until tomorrow that which can be done today.” In general, that is wise advice. However there are some cases where you do want to wait until the last possible moment to do (or not do) something. In fact, that is one of the overall tenets of  Agile Programming; delay decisions until the last possible moment because you always know more about a problem tomorrow than you do today and can make a better, more informed decision. But, I digress. I’m not here to talk about philosophies of life, or to introduce another “agile methodology” or even about a new weight loss plan based on bacon, lard and cheese puffs.

How many of you have written this same bit of boilerplate code or something similar over and over again?


if OSVersion >= 5.0 then
begin
Module = LoadLibrary('kernel32.dll');
if Module <> 0 then
begin
Proc := GetProcAddress(Module, 'APICall');
if Assigned(Proc) then
Proc(Param1, Param2);
end;
end else
{ gracefully fallback }

 


What if you could just do this?


if OSVersion >= 5.0 then
APICall(Param1, Param2);
else
{ gracefully fallback }

 


The astute among you would immediately see that with previous Delphi releases, the second form, while certainly preferable, at some point the call to “APICall” would eventually have to effectively go through some bit of code similar to the first bit of code. Normally, you would declare an external API reference like this:


procedure APICall(Param1, Param2: Integer); stdcall; external 'kernel32.dll' name 'APICall';

That will cause the linker to emit a external reference into the executable binary that is resolved at load time. Therein lies the problem. That is the situation that the first bit of code above was designed to avoid. If APICall didn’t existing in ‘kernel32.dll’ at load time, the whole application would fail to load. Game over. Thanks for playing. Now, what if you could write code similar the second block of code above and still declare your external API calls in a manner similar to above?


Starting with Delphi 2010, you can do exactly the scenario I describe. To make the second code block work even if “APICall” isn’t available on the version of the OS on which your application is currently running, we’ve introduced a new directive to be used only in the above context, delayed;

procedure APICall(Param1, Param2: Integer); stdcall; external 'kernel32.dll' name 'APICall' delayed;


Simply put, by adding the delayed directive, that instructs the linker to generate the external API reference differently in the executable binary. Now Delphi’s RTL will take care of all that ugly “late-binding” boilerplate code for you. Rather than generating the import in the normal “Imports” section of the executable’s PE file, it is generated into the “Delayed Imports” section following the published PE spec. This also requires that the RTL now has a generic function that does the proper lookups and binds the API whenever it is called the first time. Subsequent calls are just as fast as a normal import.


This is different than similar functionality available in ILink32 from C++Builder wherein you can only specify an entire dll in which all references are delay loaded. Also, in C++ you cannot specify kernel32.dll or even ntdll.dll to be delay loaded, since the very startup of any application or dll requires them to already be loaded. In Delphi you can, since it is on an API-by-API basis. The intent of this feature was to make managing all the new APIs from Windows Vista and now Windows 7 much easier without having to continuously and manually write all the delay loaded boilerplate code. Throughout VCL, we can simply make runtime decisions on which APIs to call without always going through those manually coded “thunks.” They are now simply handled by the compiler/linker and the source code barely reveals the fact that something is late-bound.


In a future release, we are considering adding both the API-by-API capability to C++Builder and a way to specify an entire dll to be late-bound in Delphi.

Friday, August 21, 2009

The “Nitty Gritty” details on Casting an Interface Reference in Delphi 2010

Malcolm Groves let loose on a new Delphi compiler feature where you can now cast an interface reference to the implementing Delphi class. Joe White was interested in the “gritty” details about how this was implemented. It turns out that it was deceptively easy once I figured out the internal compiler logic for handling “is” tests and “as” and hard casts. All three cases use the same internal mechanism implemented in the Delphi RTL.

Because all Delphi interfaces have three core methods, QueryInterface, _AddRef, and _Release, you know that you can always call QueryInterface on any interface reference. QueryInterface is declared thusly:

function QueryInterface(const IID: TGUID; out Obj): HResult; stdcall;

The last parameter is an “untyped out” parameter meaning that it will accept a reference to any variable of any type. What if you called QueryInterface with a special GUID (remember, GUID = Globally Unique IDentifier) and instead of assigning an interface reference to the Obj parameter, the implementing class instance was assigned instead? The base implementation of QueryInterface simply calls TObject.GetInterface. It is in that method that code will now look for this special GUID (which is declared in the implementation section of System.pas) and assign Obj the object reference instead of a new interface reference.

Granted, this technique does have a couple of potential issues. If, for some reason, the user decides to manually implement QueryInterface and never calls TObject.GetInterface, then none of the above casting and “is” testing will work. It will behave as if the implementing class was not implemented in Delphi. Another caveat, is if you’re doing cross-process marshaling of interfaces where both sides are Delphi 2010, you should not attempt to use this technique. In fact, if you’re doing any kinds of traditional COM programming, using this feature can yield strange results. This feature was a direct result of many requests from customers who are using interfaces for purposes outside COM.

Thursday, August 20, 2009

A Tempest in a Teapot or something more sinister?

If you’re a well connected internet maven who also happens to be a Delphi user, you’re probably no doubt aware of some of the recent reports about a new virus/trojan threat that hits pretty close to home. There are many reports among the mainstream internet press that are discussing the emergence of a virus affectionately known as the “Compile-a-virus” or by the more mundane and sanitary name, W32/Induc-A. It seems that this particular virus is targeting older versions of Delphi (specifically Delphi 4-7) and replicates itself by rebuilding a new version of SysConst.dcu and placing in back in your <root>\Lib folder. Ironically, it doesn’t simply overwrite the existing SysConst.dcu without first backing up the original, called SysConst.bak. It does use the existence of this .bak file as a signal that it’s already done its job and it should just leave that installation alone. Because it doesn’t actually delete anything, it is a gentleman among viruses ;-). Once Delphi is infected, every executable and dll that is built which links in the code in SysConst.dcu will now carry the virus which when run will seek out any Delphi installation and the process repeats.

Aside from the pure mechanics of how this thing works, there are also a lot of response among the community and press from “OMG, the sky is falling” to “nothing to see here, move along.” Fear mongering is just as bad of a response as ignoring the problem. At this point, here at Embarcadero, we’re actively analyzing situation and overall impact to our community. We’re also working on recommendations about how to find out if you’re infected and what to do once you see that you are. Throughout all this we’re working on recommended steps can you take to guard against re-infections. Rest assured that we’re neither ignoring this threat, nor are we going to do anything to blow it out of proportion. All signs indicate this is a serious and credible threat and users should remain diligent in ensuring that they either install or update their virus scanners. Many of the popular freely available scanners are now able to detect this threat, both in compiled binaries and are able to detect an infected SysConst.dcu.

As we get more information and have more recommendations, we’ll make it available. Moving forward we’re brainstorming about possible solutions that you, the customer, can use to be not only guard against future similar threats, but also if a new threat were found there can be a prescribed mechanism to detect and correct the problem.

Monday, July 6, 2009

One Year In.

Now that we’re officially one year into the whole transition from being part of Borland and now part of Embarcadero Technologies, I figure it is now safe to show this. When the CodeGear segment of Borland was announced, we scrambled to produce the ever-important t-shirts and other CodeGear branded items. Since the intent was to clearly indicate that CodeGear was from Borland, we came up with a tagline. The official tagline was “CodeGear: A new company born of Borland”
Nice clean message. Clear marketing. However, I wanted to put my own slant on this. So I fired up my wife’s really nice computer controlled embroidery sewing machine and prototyped my own version of the new CodeGear logo. I even have a shirt with this embroidered on it.

I think this expresses my true feeling about the state of developer tools under the tutelage of Borland. Given the state Borland is currently in, I think we came out ahead in the game, no?

Friday, May 29, 2009

Better smart-linking through class construction

Singletons, global services, and initialization. Most Delphi folks (myself included) don't really think about the impact of these things on how much code is being linked into their application. How many of you have your own stable of utility functions scattered throughout some number of units? You rely on these things everyday and would tend to feel naked without them. Even when you bang out that little test or utility app, those units are the first thing that goes into your uses clause. Have you ever stopped to think what impact they may be having the size of your little app? Long time Turbo Pascal and Delphi programmers have always taken for granted the smart-linker and its ability to ensure that only the code that was "touched" is what is actually linked into your final application. However, there are a lot of things we unwittingly do that can undermine the linker's "smartness." Try this little experiment; create a new console application, add all your favorite utility units to the uses clause and compile,  making sure building with packages is off. Now look at the size of your resulting executable. OMG! It does nothing, yet it is > xxxxK! Let's look at something we're working on to help you (and us) out.

As was mentioned at Delphi Live! several weeks ago, we're currently working on adding what we're calling "Mouse/Touch Gesture support" to VCL. This will eventually evolve into full multi-touch as the OS services and hardware becomes available. Initially we've been building our own "gesturing engine" and adding it throughout the VCL. From the outset, we knew that baking this support into the core of VCL was going to be key to its acceptance. At the same time we also know that there are many of you that don't need or want all that extra code slathered throughout core VCL. We also wanted to make sure this new gesturing support was "pluggable" at many levels. I'm not going to cover details about how this whole subsystem works, but simply want to use it as an example of something else we're looking at adding to the Delphi language.

Traditionally, if you had some set of classes that required some kind of global initialization or a class that was a singleton, you would place this startup code into the unit initialization section. Unfortunately, this has the side effect of dragging into the resulting binary all code and data that is directly and indirectly touched by the initialization code. Simply "using" the unit will drag in the code. Sometimes that is what you want, but what if all you wanted to do was use some other class or call some disconnected utility function within that unit? You have to pay the size and startup performance costs associated with initializing classes and data that you never even use in your own code.

Over the years, there are some "tricks" we've all played to try to get around this. The most common is in the case of singletons, where we "hide" the singleton instance behind a global function that will initialize the instance when it is first called. The problem is that everyplace you use the singleton, you incur a function call. Other tricks include injecting into each public method of an object, code that calls a helper method that does the global initialization. This also has the side-effect of incurring this call for each method. The interesting thing is that the compiler already has mechanisms in place to figure whether or not you're "touching" a given class or not. Why not just trigger on that and call an initialization method, if and only if that class is referenced someplace in code your. This really means whether or not the reference graph can trace all the way back to the main program block.

Enter class constructors. We're talking native Delphi here. Delphi for .NET and Delphi Prism have had class constructors all along since that is a concept that is baked into the .NET Common Language Runtime (CLR). However, there has never been the equivalent concept in Delphi for Win32. We're looking at fixing that. What if the following simple singleton pattern were possible?

unit SingletonUnit;

interface

type
TSingleton = class
private
class var FSingle: TSingleton;
class constructor Create;
public
procedure DoSomething;
class property Instance: TSingleton read FSingle;
end;

implementation

class constructor TSingleton.Create;
begin
FSingle := TSingleton.Create;
end;

procedure TSingleton.DoSomething;
begin
end;

end.

Now you can simply access the singleton by TSingleton.Instance.DoSomething; Because of the class constructor, the compiler will ensure that it is called long before you actually call "DoSomething" on the Instance class property. The astute among you have probably already spotted the hole in the above case. There's a memory leak now. How is the FSingle field destroyed? This is where the non-garbage-collected world of native Delphi has to do a little more work. The class destructor is how this will be handled.


  private
class var FSingle: TSingleton;
class constructor Create;
class destructor Destroy;
public
...
class destructor TSingleton.Destroy;
begin
FSingle.Free;
end;

Now let's look a little at how this all works. Class constructors (or type initializers) differ from instance constructors in that it is execute before any methods can be called or instances of the class constructed. The only rule is that it needs to run before anything else. How long before is largely irrelevant. Unlike class constructors in .NET, you cannot explicitly call them in Delphi Win32.  For Delphi Win32, class constructors are called in a manner similar to unit initialization. The difference is that the compiler treats them as a "weak reference." The class constructor is only explicitly called if other code references the class. Class constructors are called prior to the unit initialization getting called for the unit in which the class with the class constructor resides. If one class constructor references another class with a class constructor in the same unit, the compiler attempts to order the constructor calls such that deepest reference is called first. Beware of cycles! If you have several classes with class constructors within the same unit and they all refer to one-another, the ordering may be indeterminate and you may end up with strange results or even crashes. So be careful before you decide to add them to that huge morass of spaghetti code you inherited from your predecessor. For class destructors, they are called in the exact reverse order of the class constructors and are called after a given unit's finalization section is executed.


Back to the gesture engine. How does this all relate? When you drop a TGestureManager component onto a form, the designer/code manager adds an instance field of type TGesureManager to the designed form class. There is also a reference to the unit in which that component is declared added to the uses clause. The mere addition of the unit to the uses clause isn't what causes the gesture engine to be initialized, it is the component reference on the form itself that does this. If you removed the component from the form and the reference is deleted and left the uses clause reference, all that would be linked in would be a stub initialization/finalization from the given unit.


I'm already seeing several places throughout the Delphi RTL and VCL that would benefit from this. What if you wanted to use function from SysUtils, but did not want to incur the extra weight of full exception support? We may add a class constructor to the base Exception class that hook up the proper functions in System. There are probably many more places in the RTL and VCL that could be refactored in this manner. Of course we need to be cognizant of the fact that going too far may introduce strange ordering differences and could make some things behave badly or radically different. While this isn't some kind of magical "incredible shrinking machine," it is another tool that can be easily leveraged as we are adding and improving the VCL libraries. We will be able to add significant functionality without grossly impacting the minimum core set of code.

Tuesday, May 19, 2009

Yes, Virginia, there is a Delphi MacOSX and Linux project...

I guess the proverbial cat is now out of the bag. As was shown in the Delphi/C++Builder roadmap at Delphi Live!, Project X has been under way for a while now. So now you know some of the reason why things have been rather quiet here since I could not really talk about what I'm working on. The good news is that we now have a returning top-shelf engineer working on the compiler. This person was heavily involved with the original Delphi on Linux project, so there is a lot of institutional knowledge that he's able to bring to the table. Things are going to be done

Another noteworthy item is that the information in the roadmap was more about future technology rather than specific releases. In fact, for the first time in nearly as long as I can remember, we literally have several parallel efforts going on. Unlike the previous Delphi on Linux era where the teams were bounced back and forth between the Windows and Linux projects, we're keeping a smaller, more focused team engaged on "future" work with minimal distractions. Of course the "next" product release will always engage the majority of the team, but having several "background threads" of development adds a truly exciting dynamic to the team.

So if you're at all interested in some tidbits of information about the technology behind Project X and some interesting insight into a lot of the really low-level bit-twiddley aspects of the Delphi compiler and how it integrates with a new platform (and even an "old" platform like Linux) you really must check out Eli Boling's new blog. In fact, he's already starting posting some pretty gnarly stuff about some of the more goofy aspects of the Mac OS. Oh, and if you know the definitive answer to this question on Stack Overflow, please post it there.

So strap in, hang on, it's going to be an interesting ride :-).

Wednesday, May 13, 2009

Delphi Live! Here I Come

As always, I'm just now completing the slides and demos for my Delphi Live! talk. That is about par for the course... So bright and early tomorrow morning, I'll be driving past my normal exit and heading on over the Santa Cruz Mountains to downtown San Jose. Hopefully traffic will allow me to get there in plenty of time to get to the Opening Keynote on time. I've been following some of the Twitter traffic for the pre-conference sessions. So far it looks like the response has been very positive. Tomorrow evening is the "Bea^H^H^HMeet the Team" session and hope to meet many of the attendees. If you're coming to Delphi Live!... see ya there!

Friday, May 1, 2009

Product Leadership Team, Research, Weaver, Delphi Live! - Oh my!

First of all I must apologize profusely for the dearth of posts here over the last few months. OK, "dearth" in this case would unfortunately, be an overstatement since the last thing I posted here was right after the Microsoft Professional Developers Conference. While I do have explanations for this silence, I don't view them as excuses. Excuses are something that one does to deflect responsibility and blame off themselves. So I make no excuses and take full responsibility for the decided lack of posting I've done over the last few months. Certainly, some of the reasons for remaining silent here can be attributed to major distractions and that I could not talk about the stuff I've been working on. Other reasons are far less interesting and boil down to pure laziness and lack of motivation on my part. The good new is I now do have some stuff to talk about and the motivation to do has finally come back :-) Let's get started... again.

 

Product Leadership Team

Last fall, Embarcadero formed a special team that meets periodically to discuss all kinds of things about the products, their direction, markets, technology, etc... Another charter for this team is to identify technologies and market trends and to think of ways we can either leverage, drive and or otherwise participate in any of these emerging trends or markets. Or not. Deciding to not pursue a market or trend is just as valid of an outcome as deciding to do something. I'm able to be involved with this team that includes our CTO, James Pitts and our VP of Products, Michael Swindell, and at times Wayne Williams, the EMBT CEO. There are also a couple of other very senior engineers on this team with whom we can really do deep dives into technology and ideas.

Late last year, the PLT commissioned some research and even some preliminary development on some new product directions. Myself and a couple of other senior engineers have been off feverishly toiling away at this. It is this work I've been doing over the last few months that I've been unable to really talk about. There are two main reasons for remaining silent. First of all, as with any research project, it could be cancelled or shelved at any time. We don't want to talk too much about something that, while exciting, may never come to fruition. Secondly, what I talk about early into the research may have zero or nearly zero bearing on the final outcome. The good news is that it is very likely that some sneak peaks will be coming at the Delphi Live! conference in San Jose, CA. So, if you haven't signed up yet, now is the time.

 

Weaver

Hopefully by now you've heard about the next major RAD Studio release, code-named Weaver. You can even apply to field-test this new version here. If you want to see what coming in the next release and feel you have some valuable feedback, make your case and apply to participate by clicking on the above link (posting a comment here won't work). Again, if you're coming to Delphi Live! there is certain to be some information and demos with Weaver.

 

Delphi Live!

In case you haven't guessed, a common theme throughout this post is to stress the importance of attending the first face-to-face Delphi and C++Builder centric conference and the first major conference with Delphi content in over 4 years since the last Borland Conference. I will be there doing a talk on a lot of the newer designer features that have been introduced over the last 4 or 5 Delphi releases. I'll cover things like guidelines, property filters, and maybe even some new stuff coming in Weaver. I'll also be helping out with the Product Address and any "What's Cooking in the Labs?" discussions. There will also be a meet-the-team session where you can come meet nearly the entire RAD Studio development team and get your chance to corner one of us to discuss your favorite product feature or even the lack thereof :-). I'll see you all there!