21 May 2013 @ 2:37 AM 

Sometimes you need to create temporary files. Usually, you can discard those temporary files by opening them in a fashion so they are deleted when they are closed. However, in some cases, you are dealing with a library or other class that is very picky about what you give it. Other times, you create an entire directory and want that directory to be deleted when you application is closed.

Whatever the case, there are several approaches to this. The first and most obvious (to me) was to try to use C#/.NET’s Disposable interface pattern. By creating a static List of those objects, we can ensure their Dispose()/Finalizers are run when the application is terminated (static variables and fields are disposed when the application is being torn down). Then the logic to delete and attempt to delete the file can be placed in the Dispose() method as needed. My implementation originally encountered problems with sharing violations- since the application, early on, may have many handles open. Primarily, this likely occurs because of the non-deterministic nature of how static objects are disposed; so if a File is opened and is in another static member, it might not have been disposed when our dispose method is called. As a result I’ve added a Delayed invoke method which, if the delete fails initially, will call itself again after a second (trying up to five times).

  1. /// <summary>
  2. ///     Rudimentary class that is instantiated with the name of a folder, and deletes that folder when the class instance is disposed.
  3. /// </summary>
  4. public class DeletionHelper : IDisposable
  5. {
  6.     //helper native methods.
  7.     private static readonly Queue<DeletionHelper> QueuedDeletions = new Queue<DeletionHelper>();
  8.     private readonly String mDeleteThis = "";
  9.     public DeletionHelper(String deletefolder)
  10.     {
  11.         mDeleteThis = deletefolder;
  12.     }
  13.     public String DeleteThis
  14.     {
  15.         get { return mDeleteThis; }
  16.     }
  17.      [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
  18.     private static extern bool MoveFileEx(
  19.         string lpExistingFileName,
  20.         string lpNewFileName,
  21.         MoveFileFlags dwFlags);
  22.     public static void QueueDeletion(String FileOrDir)
  23.     {
  24.         var dh = new DeletionHelper(FileOrDir);
  25.         QueuedDeletions.Enqueue(dh);
  26.     }
  27.     ~DeletionHelper()
  28.     {
  29.         Dispose();
  30.     }
  31.     #region IDisposable Members
  32.     private int delaycount;
  33.     public void Dispose()
  34.     {
  35.         try
  36.         {
  37.             if (Directory.Exists(mDeleteThis))
  38.             {
  39.                 Debug.Print("Deleting folder:" + mDeleteThis);
  40.                 Directory.Delete(mDeleteThis, true);
  41.             }
  42.             else if (File.Exists(mDeleteThis))
  43.             {
  44.                 int AttemptCount = 0;
  45.                 try
  46.                 {
  47.                     AttemptCount++;
  48.                     Debug.Print("Deleting File:" + mDeleteThis);
  49.                     File.Delete(mDeleteThis);
  50.                 }
  51.                 catch (IOException e)
  52.                 {
  53.                     if (AttemptCount == 10)
  54.                     {
  55.                         return; //give up!
  56.                     }
  57.                     Thread.Sleep(250);
  58.                 }
  59.             }
  60.         }
  61.         catch (IOException ioe)
  62.         {
  63.             delaycount++;
  64.             if (delaycount > 5)
  65.             {
  66.                 //schedule for reboot deletion.
  67.                 ScheduleRebootDeletion();
  68.                 return;
  69.             }
  70.             DelayCall(new TimeSpan(0, 0, 0, delaycount), Dispose);
  71.         }
  72.     }
  73.  
  74.     private static void DelayInvokeThread(Object parameters)
  75.     {
  76.         var acquireparam = (Object [] ) parameters;
  77.  
  78.         var useaction = acquireparam [1]  as Action;
  79.         var waittime = (TimeSpan) acquireparam [2] ;
  80.         var startdelay = (DateTime) acquireparam [3] ;
  81.         while (DateTime.Now – startdelay < waittime)
  82.         {
  83.             Thread.Sleep(0);
  84.         }
  85.         if (useaction == null) return;
  86.         useaction();
  87.     }
  88.  
  89.     private static void DelayCall(TimeSpan waittime, Action routine)
  90.     {
  91.         var usethread = new Thread(DelayInvokeThread);
  92.         usethread.Start(new Object []  {usethread, routine, waittime, DateTime.Now});
  93.     }
  94.  
  95.     private void ScheduleRebootDeletion()
  96.     {
  97.         try
  98.         {
  99.             if (!MoveFileEx(mDeleteThis, null, MoveFileFlags.DelayUntilReboot))
  100.             {
  101.             }
  102.         }
  103.         catch (DllNotFoundException dlex)
  104.         {
  105.         }
  106.     }
  107.  
  108.     #endregion
  109.  
  110.      [Flags]
  111.     internal enum MoveFileFlags
  112.     {
  113.         None = 0,
  114.         ReplaceExisting = 1,
  115.         CopyAllowed = 2,
  116.         DelayUntilReboot = 4,
  117.         WriteThrough = 8,
  118.         CreateHardlink = 16,
  119.         FailIfNotTrackable = 32,
  120.     }
  121. }

This implementation also gives up after a few tries and then tries to schedule the file for reboot deletion. I considered a rather insane mechanic whereby the class would store a data file in the Temporary folder, then when first constructed (eg. static constructor) it can check for that file and either create and dispose a DeletionHelper for each filename stored in that data file, or add those files to the existing list for deletion when the application terminates. However, after considering it I figured such a feature might make things more complicated than necessary.

The other idea for automatic deletion would be to use the CreateFile() API with full share permissions, and pass the FILE_FLAG_DELETE_ON_CLOSE flag to it, then close that file in the Dispose method. Here is one possible implementation:

  1. public class DeletionHelperAPI : IDisposable
  2. {
  3.     private const int FILE_FLAG_DELETE_ON_CLOSE = 0×4000000;
  4.     private const int FILE_SHARE_READ = 0×1;
  5.     private const int FILE_SHARE_WRITE = 0×2;
  6.     private const int ACCESS_NONE = 0;
  7.     private const int OPEN_EXISTING = 3;
  8.     private const int FILE_SHARE_DELETE = 0×4;
  9.  
  10.     private List<DeletionHelperAPI> Subdeletors = new List<DeletionHelperAPI>();
  11.     [DllImport("kernel32.dll", CharSet = CharSet.Auto,
  12. CallingConvention = CallingConvention.StdCall,
  13. SetLastError = true)]
  14.     public static extern SafeFileHandle CreateFile(
  15.         string lpFileName,
  16.         uint dwDesiredAccess,
  17.         uint dwShareMode,
  18.         IntPtr SecurityAttributes,
  19.         uint dwCreationDisposition,
  20.         uint dwFlagsAndAttributes,
  21.         IntPtr hTemplateFile
  22.     );
  23.  
  24.     SafeFileHandle FileHandle = null;
  25.     public DeletionHelperAPI(String FileOrFolder)
  26.     {
  27.         //if it’s a folder, create subobjects.
  28.         if (Directory.Exists(FileOrFolder))
  29.         {
  30.             //create a subdeletor for each File/folder in that file-folder.
  31.             DirectoryInfo di = new DirectoryInfo(FileOrFolder);
  32.             foreach (FileSystemInfo fsi in di.GetFileSystemInfos())
  33.             {
  34.                 Subdeletors.Add(new DeletionHelperAPI(fsi.FullName));
  35.             }
  36.         }
  37.         else
  38.         {
  39.             FileHandle = CreateFile(FileOrFolder, ACCESS_NONE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, IntPtr.Zero,
  40.                 OPEN_EXISTING, FILE_FLAG_DELETE_ON_CLOSE, IntPtr.Zero);
  41.         }
  42.  
  43.  
  44.  
  45.     }
  46.  
  47.     public void Dispose()
  48.     {
  49.         if (Subdeletors != null)
  50.         {
  51.             foreach (var iterate in Subdeletors)
  52.             {
  53.                 iterate.Dispose();
  54.             }
  55.         }
  56.         if (FileHandle != null)
  57.         {
  58.             FileHandle.Dispose();
  59.         }
  60.     }
  61. }

And so, that gives us two implementations. I currently use the first in BASeBlock for deleting the temporary files and folders that are sometimes created during start-up, particularly if it finds a Zip file (which may have additional content that it checks for). Since those extracted files may be used during the run, I use the class to make sure they are deleted when the Application exits; or at least make an effort to do so.

70 total views, 2 views today

Posted By: BC_Programming
Last Edit: 21 May 2013 @ 02:37 AM

EmailPermalinkComments (0)
Tags
Tags: , ,
Categories: .NET, C#
 13 Apr 2013 @ 3:55 AM 

Integrated Development Environments. These are the programming tools that most of us have come to almost take for granted. They provide the ability to write, debug, edit, and otherwise develop our software within a cohesive software product. You can find Development Environments for nearly every language platform. Microsoft Visual Studio can handle C#, VB.NET, F#, and C++ out of the Box, while also providing a wealth of other language capabilities through aftermarket software. Java has Eclipse and Netbeans, just to name two- the list goes on.

However, for every IDE user, there is a person who ‘looks down’ on the lowly IDE user; “they aren’t actually writing code” they grumble into their bag of cheetos- they are simply selecting things from an autocomplete list. These types of people are, perhaps in a statistically significant way, usually users of *nix based systems. They extoll the virtues of their favourite text editor- emacs, vim, nano, and look down on IDEs, which they will sometimes refer to as “glorified text editors”.

If my patronizing tone in the previous paragraph was not obvious- or if you’ve never read one of my programming-oriented blog entries, I’m firmly on the side that supports and uses IDEs, wherever they are available. The arguments against them are often lame; arguing that getting used to a feature like autocomplete or parameter lists, or dynamic help windows, and tips and whatnot make us “soft” is absurd- the same could be said of keyboards- by extension it just makes inputting data easier, so clearly we should be flipping switches manually. My point is that IDE software aims to make the task of software development easier, and more productive. And IMO it does this is spades.

There are even add-ins for many IDEs that basically provide all sorts of world-class capabilities in the IDE. Resharper is one exceptional such plugin that is available for Visual Studio- at this point, if it’s missing, it’s like I’m missing an appendage. It has made my work in Visual Studio so much more enjoyable and productive, that I almost feel it’s a crime not to have it installed. Similar addons are available for all sorts of IDEs; even Visual Basic 6 has things like MZTools(Free) or AxTools CodeSMART(Commercial).

Of course, IDEs lose a lot of their edge in certain languages, particularly those that lean towards the dynamic end of the spectrum. So much information about the program relies on run-time, that it’s a tricky proposition for a piece of software to try to figure out what is going on and provide any sort of tips or suggestions. Unsurprisingly, most of those that find IDEs childish use languages such as Python, Perl, Ruby, and PHP; I myself do not use an IDE for these languages either; primarily because I couldn’t find one (VS 2012 has an add-in available called “PHP Tools” that apparently brings support for PHP, though I do not know the extent of it’s assistance). However, if there was a software product available that provided the same level of assistance to languages like Ruby and Python as I currently get from Visual Studio or Eclipse, I would jump on it like Mario on a Goomba.

We ought to think of the software as not only our tools, but our own assistants. Most people wouldn’t raise any objections about being given a personal assistant for their work or daily tasks. In the case of Resharper specifically, that assistant is also an 11.

176 total views, 2 views today

Posted By: BC_Programming
Last Edit: 15 Apr 2013 @ 03:49 AM

EmailPermalinkComments (0)
Tags
Tags: , , , , ,
Categories: Programming
 01 Apr 2013 @ 4:21 AM 

C#’s linq(language-integrated query) features are some of the more powerful features available through the language. Aside from it’s query operators that are, as it’s name would suggest, integrated into the language, the feature also brings along a large set of Extension methods to the IEnumerable interface type.

One interesting re-use of the IEnumerable type for extension methods is to create ad-hoc language structures using it, for example:

  1. class Program
  2. {
  3.     static void Main(string []  args)
  4.     {
  5.         Random rgen = new Random();
  6.         var doubles = (from p in Enumerable.Range(0, 100) select rgen.NextDouble());
  7.         doubles.EachCase(
  8.             (t) => t < 0.5d,
  9.             (value) =>
  10.             {
  11.                 Console.WriteLine(value.ToString() + " is less than 0.5d.");
  12.             }).EachCase(
  13.             (t) => t > 0.75d,
  14.             (value) =>
  15.             {
  16.                 Console.WriteLine(value.ToString() + " is greater than 0.75d.");
  17.             }).EachCase((t) => true,
  18.             (value) =>
  19.             {
  20.                 Console.WriteLine(value.ToString() + " is not handled…");
  21.             }).Count();
  22.         Console.ReadKey();
  23.     }
  24. }

What we have here is similar- but not quite the same- as a switch statement within a loop. What makes this particularly interesting as a structure is that it acts sort of like a seive. The source to the extension EachCase() method is shown here:

  1. public static class SelectExtension
  2. {
  3.     public static IEnumerable<T> EachCase<T>(this IEnumerable<T> Enumeration,Func<T,bool> TestExpression,Action<T> CodeBlock)
  4.     {
  5.  
  6.         if (Enumeration == null) yield break;
  7.         foreach (var iterate in Enumeration)
  8.         {
  9.             if (TestExpression(iterate))
  10.             {
  11.                 CodeBlock(iterate);
  12.  
  13.             }
  14.             else
  15.                 yield return iterate;
  16.         }
  17.      }
  18. }

The function works by calling the passed Action for all entries in the enumeration that cause TestExpression to return true. Those that return false are yielded to the caller. In the original code the EachCase() calls were chained, one after the other; each one operated on the entries that the previous one didn’t work with. the final .Count() call in the original code is to force it to be enumerated, allowing all the code blocks to evaluate appropriately. What use-cases might this have? I have no idea. However I feel confident in saying that it could make for a more readable alternative to something that might otherwise require a separate Finite-State machine.

320 total views, no views today

Posted By: BC_Programming
Last Edit: 01 Apr 2013 @ 04:21 AM

EmailPermalinkComments (0)
Tags
Tags: , , ,
Categories: .NET, C#
 21 Mar 2013 @ 9:08 AM 

Most application frameworks/languages provide access to the Command Line parameters passed to your application. Generally it is passed to your application as either a string or an array of strings. What you do not get automatically is the functionality to parse out switches.

Command-line parameters used to be the only way to communicate with a program. Fundamentally, the command line was your UI into the program. Different platforms took different approaches. Unix-like systems typically take the “invasive” route; they replace wildcards and then pass the resulting command line to the application. This means that you don’t have to do any shell expansion of wildcards (as it is known) but you have to account for the fact that your command line could include a lot of files. It’s a trade-off, really. Either way, I figured for the purposes of this library, we could stick to the platform- if the program is run with a wildcard, you’ll see the wildcard on windows, but it will have been expanded if you run the same program on Linux. It might be worth adding an option to “auto-expand” wildcards- just for consistencies sake, but that seems like a post for another day.

Either way, most applications also include flags and switches. This is more a De Facto standard that has cropped up- there is no hard and fast rulebook about what flags and switches are or how you are supposed to pass arguments, which can cause no end of confusion when it comes to reading application documentation. the .NET language just gives you the string, and leaves it up to you to decide how to interpret it. Some language libraries provide functionality to parse the Command Line appropriately, such as Python. C# doesn’t come with such a class…. So let’s make one!

First we need to determine what exactly can exist in a command line. My method allows for two things: Switches, and arguments. A Switch can include an argument, separated from the switch with a colon. For example:

  1.  
  2. someprogram.exe /switch:argument /sw:"file 1.txt" "filename.txt" /doall
  3.  

In this case, we have three switches- switch, sw, and doall. The first two include an argument. My “syntax” allows for quotes in the arguments of switches as well as the “loose” arguments. We will evidently need classes to represent and parse Arguments, and another one for Switches. The parsing can be done sequentially. Although it’s not a recommended best practice, I chose to use by reference parameters in the class constructors. In order to keep things generic and accessible, both Switches and Arguments will derive from a CommandLineElement abstract class, which will force each base class to implement toString(). the ArgumentItem class will be used for parsing both “loose” arguments, as well as arguments found after a switch.

Arguments

Arguments are simple- if the first letter of the position is a quote, we look for the next quote that isn’t doubled up. Otherwise, we look for either the next whitespace or the end of the string. Each argument only needs the actual argument value.

  1.  
  2.   /// <summary>
  3.         /// Represents an Argument. This includes arguments that exist bare on the command line as well as arguments used with a given switch.
  4.         /// </summary>
  5.         public class ArgumentItem : CommandLineElement
  6.         {
  7.             public static ArgumentItem Empty = new ArgumentItem();
  8.             private String _Argument;
  9.  
  10.             protected internal ArgumentItem()
  11.             {
  12.                 _Argument = "";
  13.             }
  14.  
  15.             /// <summary>
  16.             /// Construct an Instance from the given string, assuming the start of an Argument element at the given position.
  17.             /// </summary>
  18.             /// <param name="strParse">Command Line to parse.</param>
  19.             /// <param name="Position">Location to start. This variable will be updated with the ending position of the argument that was discovered upon return.</param>
  20.             public ArgumentItem(String strParse, ref int Position)
  21.             {
  22.                 int startpos = Position;
  23.                 int sloc = startpos;
  24.                 while (char.IsWhiteSpace(strParse.ElementAt(sloc))) sloc++;
  25.                 if (strParse.ElementAt(sloc) == ‘"’)
  26.                 {
  27.                     sloc++;
  28.                     while (true)
  29.                     {
  30.                         if (sloc >= strParse.Length) break;
  31.                         bool doublequote = strParse.Length > sloc + 2 && strParse.Substring(sloc, 2).Equals("\"");
  32.                         //if we found a quote and it’s not a double quote…
  33.                         if (strParse.ElementAt(sloc) == ‘"’ && !doublequote)
  34.                         {
  35.                             sloc++;
  36.                             break;
  37.                         }
  38.                         if (doublequote) sloc++; //add an extra spot for the dual quote.
  39.  
  40.                         sloc++;
  41.                     }
  42.                 }
  43.                 else
  44.                 {
  45.                     sloc = strParse.IndexOfAny(new char []  {‘/’, ‘ ‘}, sloc);
  46.                 }
  47.                 _Argument = strParse.Substring(Position, sloc – startpos);
  48.                 Position = sloc;
  49.             }
  50.  
  51.             /// <summary>
  52.             /// returns the Argument this Object represents. This will include quotation marks if they were used in the originally parsed string.
  53.             /// </summary>
  54.             public String Argument
  55.             {
  56.                 get { return _Argument; }
  57.             }
  58.  
  59.             /// <summary>
  60.             /// implicitly converts an ArgumentItem to a String.
  61.             /// </summary>
  62.             /// <param name="value">ArgumentItem to implicitly convert.</param>
  63.             /// <returns>the result from calling Chomp() on the given instance.</returns>
  64.             public static implicit operator String(ArgumentItem value)
  65.             {
  66.                 return value.Chomp();
  67.             }
  68.  
  69.             /// <summary>
  70.             /// returns the Argument value. If it starts with and endswith quotation marks, they will be removed.
  71.             /// </summary>
  72.             /// <returns></returns>
  73.             public String Chomp()
  74.             {
  75.                 if (_Argument.StartsWith("\"") && Argument.EndsWith("\""))
  76.                     return _Argument.Substring(1, _Argument.Length2);
  77.                 else return _Argument;
  78.             }
  79.  
  80.             public override string ToString()
  81.             {
  82.                 if (Argument.Any(Char.IsWhiteSpace))
  83.                     return "\"" + Argument + "\"";
  84.                 else return Argument;
  85.             }
  86.         }
  87.  

The constructor is where the important stuff happens. the by reference parameter is used to define the starting position, and we update it when the constructor returns to point at the character after the argument. The class also defines some statics for implicit conversions to and from a string.

Now that we have the Argument class, we can define the Switch class. The actual syntax of switches often depends on the application but also seems to depend on the platform. for example, Linux tools favour the hyphen for single letter flags, and double hyphens for multi-character flags. Switches are also called flags. forward slash is not generally used as a switch or flag indicator. Windows platforms prefer the forward slash but generally allow for single hyphens as well. We aim to support all three syntaxes, and make the client application not have to worry about which it is. We also add support for arguments- a switch can be specific as such:

 
someprogram /d:argument.exe
 

The element after the colon will be parsed as an argument and attached to the switch itself. But enough waffling- on to the Switch:

  1. public class Switch : CommandLineElement
  2. {
  3.     internal static String []  SwitchPreceders = new string []  {"–", "-", "/"};
  4.     private ArgumentItem _Argument = ArgumentItem.Empty;
  5.     private String _SwitchValue;
  6.  
  7.     public Switch(String strParse, ref int StartLocation)
  8.     {
  9.         while (String.IsNullOrWhiteSpace(strParse.ElementAt(StartLocation).ToString())) StartLocation++;
  10.         var sLoc = StartLocation;
  11.         var retrieved = SwitchPreceders.
  12.             FirstOrDefault((s) => !(sLoc + s.Length > strParse.Length) &&
  13.                                   strParse.Substring(sLoc, s.Length)
  14.                                           .Equals(s, StringComparison.OrdinalIgnoreCase));
  15.         if (retrieved == null)
  16.         {
  17.             throw new ArgumentException("Passed String " + strParse +
  18.                                         " Does not have a switch preceder at position " + StartLocation);
  19.         }
  20.         var NextSpace = strParse.IndexOfAny(new char []  {‘ ‘, \t, ‘/’, ‘:’}, sLoc + 1);
  21.         //if(((NextSpace-sLoc)-sLoc+1) <= 0) throw new ArgumentException("Error Parsing Switch");
  22.         _SwitchValue = strParse.Substring(sLoc + 1, NextSpace – sLoc – 1);
  23.         sLoc += retrieved.Length; //we don’t want the switch itself.
  24.         //now we need to determine where the Switch ends. colon or space seems reasonable. If a colon, the next entity will be an argument.
  25.         StartLocation = NextSpace;
  26.         //if the char at NextSpace is a Colon…
  27.         if (strParse.ElementAt(NextSpace) == ‘:’)
  28.         {
  29.             //interpret as an argument
  30.             NextSpace++;
  31.             _Argument = new ArgumentItem(strParse, ref NextSpace);
  32.         }
  33.         StartLocation = NextSpace;
  34.     }
  35.     public String SwitchValue
  36.     {
  37.         get { return _SwitchValue; }
  38.     }
  39.     public String Argument
  40.     {
  41.         get { return _Argument; }
  42.     }
  43.     //Constructs an instance of a switch from the given location.
  44.     public static bool SwitchAtPos(String strParse, int Location)
  45.     {
  46.         var retrieved = SwitchPreceders.
  47.             FirstOrDefault((s) => !(Location + s.Length > strParse.Length) &&
  48.                                   strParse.Substring(Location, s.Length)
  49.                                           .Equals(s, StringComparison.OrdinalIgnoreCase));
  50.         return retrieved != null;
  51.     }
  52.     public override string ToString()
  53.     {
  54.         return "//" + _SwitchValue + ":" + _Argument.ToString();
  55.     }
  56.     public bool HasArgument()
  57.     {
  58.         return _Argument.Equals(ArgumentItem.Empty);
  59.     }
  60.         }

With the basic parsing logic completed, we need to consider how we want this to be used. Best way is to think of how we would like to use them:

  1. CmdParser cp = new CmdParser();
  2. if(cp.HasSwitch("f") && cp ["f"] .HasArgument()) _usefilename=cp ["f"] .Argument;

Some basic take-aways from this. First, the Core Parser Object needs to provide an Indexer. In the above example, we see it is accessing Switches by passing in the Switch name. Other possibilities include using direct numeric indexes to refer to any argument- much like you would access elements in the framework provided args [] String array. Another possibility is to have the Argument of a switch auto-populate, rather than be null, when accessed:

  1.  _usefilename=cp.HasSwitch("f")?cp ["f"] .Argument:_usefilename;

1,154 total views, 50 views today

Posted By: BC_Programming
Last Edit: 21 Mar 2013 @ 09:10 AM

EmailPermalinkComments (0)
Tags
 04 Feb 2013 @ 9:24 PM 

Is XNA Going Away?

The following consists of my opinion and does not constitute the passing on of an official statement from Microsoft. All thoughts and logic is purely my own and I do not have any more ‘insider’ information in this particular topic than anybody else

I’ve been hearing from the community a bit of noise about Microsoft’s XNA Framework- a Programming library and suite of applications designed to ease the creation of Games- being cut. A google reveals a lot of information, but a lot of it is just plain old rumours. The only one I could find that was based on actual information still makes a lot of assumptions. It is based on this E-mail:

Our goal is to provide you the best experience during your award year and when engaging with our product groups. The purpose of the communication is to share information regarding the retirement of XNA/DirectX as a Technical Expertise.

The XNA/DirectX expertise was created to recognize community leaders who focused on XNA Game Studio and/or DirectX development. Presently the XNA Game Studio is not in active development and DirectX is no longer evolving as a technology. Given the status within each technology, further value and engagement cannot be offered to the MVP community. As a result, effective April 1, 2014 XNA/DirectX will be fully retired from the MVP Award Program.

Because we continue to value the high level of technical contributions you continue to make to your technical community, we want to work with you to try to find a more alternate expertise area. You may remain in this award expertise until your award end date or request to change your expertise to the most appropriate alternative providing current contributions match to the desired expertise criteria. Please let me know what other products or technologies you feel your contributions align to and I will review those contributions for consideration in that new expertise area prior to the XNA/DirectX retirement date.

Please note: If an expertise change is made prior to your award end date, review for renewal of the MVP Award will be based on contributions in your new expertise.

Please contact me if you have any questions regarding this change.

This is an E-Mail that was sent out- presumably- to XNA/DirectX MVPs. I say presumably because for all we know it was made up to create a news story. If it was sent out, I never received it, so I assume it would have been sent to those that received an MVP Award with that expertise. It might have been posted to an XNA newsgroup as well. Anyway, the article that had this E-mail emblazoned as “proof” that MS was abandoning XNA seemed to miss the ever-important point that it actually says nothing about XNA itself, but actually refers to the dropping of XNA/DirectX as a technical Expertise. What this means is that there will no longer be Awards given for XNA/DirectX development. It says nothing beyond that. Now, it could mean they plan to phase it out entirely- but to come to that conclusion based on this is a bit premature, because most such expertise-drops actually involved a merge. For example, in many ways, an XNA/DirectX expertise is a bit redundant, since XNA/DirectX works using a .NET Language such as VB.NET and C# and very few XNA/DirectX MVPs truly can work with XNA in any language at all, it might make sense to just clump them with us lowly Visual C# and Visual Basic MVPs.

To make the assumption that XNA is being dropped based on this E-mail is a bit premature. In my opinion, I think the choice was made for several reasons. I guess some of the misconceptions might be the result of misconceptions about just what a Microsoft MVP is. First, as I mentioned before, a lot of the expertise of XNA/DirectX involves an understanding- and expertise- in some other area. Again, Visual C#, Visual Basic, Visual C++, etc. So in some ways they might have considered a separate XNA/DirectX expertise redundant. Another reason might have to do with the purpose of an MVP. MVP Awards are given to recognize those who make exceptional community contributions in the communities that form around their expertise. For example, my own blog typically centers around C#, solving problems with C# and Visual Studio, and presents those code solutions and analyses to the greater community by way of the internet, as well as sharing my knowledge of C# and .NET in those forums in which I participate. MVP awardees don’t generally receive much extra inside information- and that they do get is typically covered by a NDA agreement. The purpose of the award is to also establish good community members with which Microsoft can provide information to the community. MVPs are encouraged to attend numerous events where they can, quite literally, talk directly to the developers of the Products with which they acquainted. in some way you could consider MVPs “representatives” of the community, who are chosen because their contributions mean they likely have a good understanding of any prevalent problems with the technologies in question, and interacting with MVPs can give the product teams insight into the community for which their product is created. Back to the particulars here, however- as the E-mail states, XNA Game Studio is not under active development. Now, following that, it seems reasonable to work with the assumption that either that product has no Product Team, or those that are on that Product Team are currently occupied in other endeavours, or other products for which their specific talents are required.

It’s not so much that they are “pulling the plug in XNA”- the product is currently in stasis. As a direct result of this, it makes sense that without an active Product Team, having specific MVP Awardees for that expertise isn’t particularly useful for either side- MVPs gain from personal interactions with the appropriate Microsoft Product team as well as fellow MVPs, and Microsoft gains from the aggregate “pulse of the community” that those MVPs can provide. Without a Product Team for a expertise, that expertise is redundant, because there is nobody to get direct feedback. This doesn’t mean the XNA community is going away, just that, for the Moment, there is no reason for Microsoft to watch it’s pulse, because the product is “in stasis” as the OS and other concerns surrounding the technology metamorphize and stabilize (The Windows 8 UI style, Windows Store, and other concerns in particular). Once the details and current problems with those technologies are sussed out, I feel they will most certainly look back and see how they can bring the wealth of game software written in XNA to the new platform. Even if that doesn’t happen, XNA is still heavily used for XBox development- which is also it’s own expertise.

I hope this helps clear up some of the confusion that has been surrounding XNA. It doesn’t exactly eliminate uncertainty- this could, in fact, be a precursor to cutting the technology altogether. But there is nothing to point to that being the direction, either.

460 total views, no views today

Posted By: BC_Programming
Last Edit: 04 Feb 2013 @ 09:24 PM

EmailPermalinkComments (0)
Tags
 01 Feb 2013 @ 10:23 AM 

Randomization is something that is pretty much a staple in games. But the tricky part is randomizing in an expected way.

Some kinds of randomization, you don’t want to be truly random- just mostly random- and you do in fact want it to go through all the possibilities more frequently, though in a random way.

The best example I can think up is to imagine you have a Enemy that can shoot forwards, backwards, up, and down. Now, targeting the player notwithstanding, let’s assume you want them to shoot randomly. If you go with the approach of just choosing a direction completely at random, you will find that the code will often choose the same direction many times in a row. This is more or less the problem with trying to randomize small sets of data. Each selected element is more or less chosen without regard to those chosen before. This fits probability, of course, but can be a bit weird gameplay wise.

Enter ItemBucket

The solution is fundamentally to make sure that items are chosen at random, but also that every item get’s used. The best solution I could think of was one where you choose elements at random, but you make sure you don’t choose the same elements twice during any one run. The class I created for this purpose I called “CItemBucket”. It’s functionality is fairly simple: it is constructed with the items it will contain. This initializes two lists with those elements. The ItemBucket can “dispense” items; when an item is dispensed, it is removed from the list. if the list is empty, it is reset from the Original List. this makes sure that in any number of elements of size N, any element in that list will occur exactly once during N dispenses. My original idea was to return a randomly indexed element each call, but then I got to thinking that, in many ways, we are simply dealing with a “shuffled deck” of elements, and returning items from that “deck”. So, at the cost of making Adding a bit more expensive, I think I was able to make the retrieval method O(n) for the number of present elements (based on the Queue implementation, that is).

Here, the, is the C# Implementation for this class:

  1.  
  2.     public class ItemBucket<T>
  3.     {
  4.         private int _dispensed = 0;
  5.         private Queue<T> _elements;
  6.         private T []  _original;
  7.         private readonly Random rgenerator = new Random();
  8.  
  9.         public ItemBucket(Random rg, params T []  source)
  10.             : this(rg, (IEnumerable<T>)source)
  11.         {
  12.         }
  13.         private IEnumerable<T> Shuffle<T>(IEnumerable<T> source)
  14.         {
  15.  
  16.             return source.OrderBy<T, int>((item) => rgenerator.Next());
  17.         }
  18.         public ItemBucket(params T []  source)
  19.             : this((IEnumerable<T>)source)
  20.         {
  21.         }
  22.  
  23.         public ItemBucket(Random rg, IEnumerable<T> source)
  24.             : this(source)
  25.         {
  26.             rgenerator = rg;
  27.         }
  28.  
  29.         public ItemBucket(IEnumerable<T> source)
  30.         {
  31.             _original = source.ToArray();
  32.             _elements = new Queue<T>(Shuffle(_original));
  33.         }
  34.  
  35.         public static T []  RepeatArray(T []  array, int count)
  36.         {
  37.             var resultarray = new List<T>(array);
  38.             for (int i = 0; i < count; i++)
  39.             {
  40.                 resultarray.AddRange(array);
  41.             }
  42.             return resultarray.ToArray();
  43.         }
  44.         public ItemBucket<T> AddRange(IEnumerable<T> Elements)
  45.         {
  46.             foreach (var iterate in Elements)
  47.             {
  48.                 _elements.Enqueue(iterate);
  49.                 var neworiginal = new List<T>(_original) { iterate };
  50.                 _original = neworiginal.ToArray();
  51.             }
  52.             _elements = new Queue<T>(Shuffle(_elements));
  53.             return this;
  54.         }
  55.         public ItemBucket<T> Add(T element)
  56.         {
  57.             _elements.Enqueue(element);
  58.             _elements = new Queue<T>(Shuffle(_elements));
  59.             var neworiginal = new List<T>(_original) { element };
  60.             _original = neworiginal.ToArray();
  61.             return this;
  62.         }
  63.         private T DispenseSingle()
  64.         {
  65.             //dispense a single item.
  66.             //get an index into the Elements array.
  67.             T retrieved = _elements.Dequeue();
  68.  
  69.             if (!_elements.Any())
  70.             {
  71.                 //no elements, so re-create from Original.
  72.                 Debug.Print("Bucket Empty!");
  73.                 _elements = new Queue<T>(Shuffle(_original));
  74.             }
  75.  
  76.             return retrieved;
  77.         }
  78.         public T Dispense()
  79.         {
  80.             return DispenseSingle();
  81.         }
  82.         public IEnumerable<T> Dispense(int count)
  83.         {
  84.             for (int i = 0; i < count; i++)
  85.             {
  86.                 yield return DispenseSingle();
  87.             }
  88.         }
  89.     }
  90.  

Here is some code that consumes this implementation:

  1.  
  2. class Program
  3.     {
  4.         static void Main(string []  args)
  5.         {
  6.             ItemBucket<int> usebucket = new ItemBucket<int>(ItemBucket<int>.RepeatArray(Enumerable.Range(0, 12).ToArray(), 3));
  7.             Console.WriteLine();
  8.             for (int i = 0; i < 120;i++ )
  9.             {
  10.                 Console.Write(i + ":" + usebucket.Dispense() + ",");
  11.  
  12.  
  13.             }
  14.             Console.ReadKey();
  15.         }
  16.     }
  17.  

Works quite well, as far as I can tell.

But wait, there’s more!

Perhaps because I like to think of myself as something of a polyglot, let’s go ahead and come up with an implementation of this for Java. Now, doing this in Java would be a bit more tricky- that is, directly. Unlike the C# implementation, we don’t have the convenience of lambda’s to make a ‘pure’ shuffle. Instead, we would have to write our own implementation. Instead of that, I went with the original concept- that is, to choose,remove, and return a random index, and re-create the Bucket contents when we’ve emptied it. Here is the Java version of this class:

  1.  
  2. import java.lang.reflect.Array;
  3. import java.util.ArrayList;
  4. import java.util.List;
  5. import java.util.Random;
  6.  
  7. public class ItemBucket<T> {
  8.     private ArrayList<T> _Elements;
  9.     private ArrayList<T> _Original;
  10.     private Random rgen = new Random();
  11.  
  12.     public ItemBucket(T… Source) {
  13.         this(new Random(), Source);
  14.     }
  15.  
  16.     public static <K> K []  RepeatArray(K []  tocopy, int copies, Class classtype) {
  17.         if (copies < 0)
  18.             throw new IllegalArgumentException("copies must be non-negative.");
  19.  
  20.         @SuppressWarnings("unchecked")
  21.         K []  resultarray = (K [] ) Array.newInstance(classtype, tocopy.length
  22.                 * copies);
  23.         for (int copy = 1; copy < copies; copy++) {
  24.  
  25.             for (int index = 0; index < resultarray.length; index++) {
  26.                 resultarray [index]  = tocopy [index % tocopy.length] ;
  27.             }
  28.  
  29.         }
  30.         return resultarray;
  31.  
  32.     }
  33.  
  34.     public ItemBucket(Random rg, T… Source) {
  35.         rgen = rg;
  36.         _Original = new ArrayList<T>();
  37.         _Elements = new ArrayList<T>();
  38.         for (T addto : Source) {
  39.             _Original.add(addto);
  40.             _Elements.add(addto);
  41.         }
  42.     }
  43.  
  44.     private T DispenseSingle() {
  45.         // dispense a single item.
  46.         // use the Random instance to get a random index.
  47.         int randompos = rgen.nextInt(_Elements.size());
  48.         // grab that element.
  49.         T retrieved = _Elements.get(randompos);
  50.         _Elements.remove(randompos);
  51.         // if the Elements list is empty, ‘refresh’ it from the Original.
  52.         if (_Elements.isEmpty()) {
  53.             _Elements.addAll(_Original);
  54.         }
  55.         return retrieved;
  56.  
  57.     }
  58.  
  59.     public T Dispense() {
  60.         return DispenseSingle();
  61.     }
  62.  
  63.     public List<T> Dispense(int Count) {
  64.         ArrayList<T> buildlist = new ArrayList<T>();
  65.         for (int i = 0; i < Count; i++)
  66.             buildlist.add(Dispense());
  67.  
  68.         return buildlist;
  69.     }
  70.  
  71. }
  72.  

Test code for the above Java implementation:

  1.  
  2. public class testItemBucket{
  3. public static void main(String []  args) {
  4.         ItemBucket<Integer> bucket = new ItemBucket<Integer>(ItemBucket.RepeatArray(new Integer [] {1, 2, 3,4,5,6,7,8,9,10},3,Integer.class));
  5.         //choose 90 items.
  6.         for(int i=0;i<90;i++){
  7.             int gotvalue = bucket.Dispense().intValue();
  8.             System.out.print(i + ":" + gotvalue + ",");
  9.         }
  10. }
  11. }
  12.  

As far as I’m concerned, the most interesting thing in the Java implementation is the “RepeatArray” method. Java’s Generic limitations prevent us from creating Arrays of the Generic Type Parameter directly, so instead we need to use some reflection magic. unfortunately, as far as I can tell there is no way to get the class of the actual type parameter in Java, so I had to resort to accepting that class as a parameter. Also, because of the lack of Generators/Enumerable methods, I ended up simply having that method return a List of the generic type, rather than an Enumerable.

It’s not over yet!

You might think, “OK, he’s covered C# and Java implementations- can I please go home. Well, yes, you can. But then you’ll miss my Python implementation! I went with the same approach I chose for Java- that is, retrieving items randomly and removing them. It’s fully possible to use the same methodology I used for the C# approach- using Queues and sorting on randomized keys- but I found this approach a bit less verbose, and more straightforward. And, it is my opinion that ‘straightforward’ is sort of the “python way”, so I went with that.

  1.  
  2. import random
  3. class ItemBucket:
  4.     def __init__(self,pelements):
  5.         #copy the provided elements.
  6.         self.elements= []
  7.         self.original= []
  8.         for iterate in pelements:
  9.             self.original.append(iterate)
  10.        
  11.         #copy the original list into the elements list.
  12.         self.elements=self.original [1:]
  13.     def DispenseSingle(self):
  14.         #select a random index.
  15.         index = random.randrange(len(self.elements))
  16.         result=self.elements.pop(index)
  17.         if not self.elements:
  18.             #if list is empty, recreate from original.
  19.             self.elements=self.original [1:]
  20.         return result;
  21.     def DispenseMulti(self,n=1):
  22.         #select n items and return them
  23.         x=0
  24.         while x < n:
  25.             yield DispenseSingle(self)
  26.             x+=1
  27.  

And, of course, the Python code that uses it:

  1.  
  2. ib=ItemBucket( [1,2,3,4,5,6,7,8,9] *3)
  3. for i in range(0,40):
  4.     print str(i) + ":" + str(ib.DispenseSingle())
  5.  

The first thing that stands out is just how much shorter this one is to either the Java or C# implementations. This is probably mostly due to the dynamic typing of Python, as well as a few syntactic shortcuts. The only “gotcha” I found was that Python didn’t really support overloaded methods. Technically, I could create one method and then verify what parameters were actually passed, but in this case I wanted one to be a Generator Method, and the other to simply return a single element. Only way I could figure out how to do that was to have separate DispenseSingle() and DispenseMulti() methods. It also doesn’t expose the innards like the other implementations, in that you cannot add Elements to an already constructed instance. In retrospect, I’m not really sure if it’s a good idea to make the design Mutable at all. The Most typical use-case would be to construct it with all the elements it will use, and not change it afterwards- that’s the use case I have in BASeBlock, and the use-case I’m considering using my Java implementation for. So having extra methods to add elements, and keep fields “fresh” and consistent adds implementation complexity for little gain.

606 total views, no views today

Posted By: BC_Programming
Last Edit: 01 Feb 2013 @ 11:46 AM

EmailPermalinkComments (0)
Tags
 20 Jan 2013 @ 8:14 PM 

One common problem that comes up in the creation of stylized windows such as Splash screens is the desire to have parts of the form be “shadowed” or, in other words, blend with the forms behind them. You can see this effect in action with other application splash screens, such as photoshop:

Photoshop Splash Screen in front of a dead-sexy website

Photoshop Splash Screen in front of a dead-sexy website

What witchcraft is this? How does Photoshop do it? One of the first things you might try with .NET is something like the TransparencyKey of the form. Of course, this doesn’t work, instead you get this unsightly ring of the transparency key around it.

The solution, of course, is a bit more complicated.

Starting with Windows 2000, the Win32 API and Window Manager has supported the idea of “layered” Windows. Before this, Windows had concepts known as “regions”; this basically allowed you to define regions of your window where the background would show through. This didn’t allow for per-pixel blending, but that sort of thing was not widely supported (or even conceived of, really) by most graphics Adapters. The “Layered” Windowing API basically provided a way to allow Per-pixel Alpha. Which is what we want.

Windows Forms, however, does not expose this layered window API through it’s methods or properties, with the exception of the opacity property. I don’t recall if WPF does either, but I would be surprised if it’s capabilities exposed more of the Layered Windowing API. Basically- we’re on our own

So what exactly do we need to do? Well, one thing we need to do is override the CreateParams property of the desired form, so that it adds the WS_EX_LAYERED style to the window, letting the Windowing Manager know it has to do more work with this window. Since we would like a neatly decoupled implementation, we are going to create a class that derives from Form, but use that as the base class for another form. This let’s us override the CreateParams property within that base class, but this has a bit of a caveat as well, since I’ve found that makes the Designer a bit annoyed and it complains and won’t let you use the designer. So you will have to deal with that particular point yourself. (I imagine there is a way to make it work, but I don’t want to bloat the class with such functionality). If necessary, the appropriate functions and the CreateParams override can be put into the classes that need this functionality instead.

Here is the PerPixelAlphaForm class. By the way, I’m going with Visual Basic.NET because there are already a million hits for this functionality with C#:

  1.  
  2.  
  3. Imports System
  4. Imports System.Drawing
  5. Imports System.Drawing.Imaging
  6. Imports System.Windows.Forms
  7. Imports System.Runtime.InteropServices
  8.  
  9.  
  10.  
  11. ‘ class that exposes needed windows GDI Functions.
  12. Public Class Win32
  13.  
  14.  
  15.     Public Enum Bool
  16.         bFalse = 0
  17.         bTrue = 1
  18.     End Enum
  19.  
  20.  
  21.  
  22.     <StructLayout(LayoutKind.Sequential)>
  23.     Public Structure Point
  24.  
  25.         Public x As Int32
  26.         Public y As Int32
  27.  
  28.         Public Sub New(x As Int32, y As Int32)
  29.             Me.x = x
  30.             Me.y = y
  31.         End Sub
  32.     End Structure
  33.  
  34.  
  35.     <StructLayout(LayoutKind.Sequential)>
  36.     Public Structure Size
  37.         Public cx As Int32
  38.         Public cy As Int32
  39.  
  40.         Public Sub New(cx As Int32, cy As Int32)
  41.             Me.cx = cx
  42.             Me.cy = cy
  43.         End Sub
  44.     End Structure
  45.  
  46.  
  47.  
  48.     <StructLayout(LayoutKind.Sequential, Pack:=1)>
  49.     Structure ARGB
  50.  
  51.         Public Blue As Byte
  52.         Public Green As Byte
  53.         Public Red As Byte
  54.         Public Alpha As Byte
  55.     End Structure
  56.  
  57.  
  58.  
  59.     <StructLayout(LayoutKind.Sequential, Pack:=1)>
  60.     Public Structure BLENDFUNCTION
  61.         Public BlendOp As Byte
  62.         Public BlendFlags As Byte
  63.         Public SourceConstantAlpha As Byte
  64.         Public AlphaFormat As Byte
  65.     End Structure
  66.  
  67.  
  68.  
  69.     Public Const ULW_COLORKEY As Int32 = &H1
  70.     Public Const ULW_ALPHA As Int32 = &H2
  71.     Public Const ULW_OPAQUE As Int32 = &H4
  72.  
  73.     Public Const AC_SRC_OVER As Byte = &H0
  74.     Public Const AC_SRC_ALPHA As Byte = &H1
  75.  
  76.  
  77.     <DllImport("user32.dll", ExactSpelling:=True, SetLastError:=True)>
  78.     Public Shared Function UpdateLayeredWindow(hwnd As IntPtr, hdcDst As IntPtr, ByRef pptDst As Point, ByRef psize As Size, hdcSrc As IntPtr, ByRef pprSrc As Point, crKey As Int32, ByRef pblend As BLENDFUNCTION, dwFlags As Int32) As Bool
  79.  
  80.     End Function
  81.  
  82.     <DllImport("user32.dll", ExactSpelling:=True, SetLastError:=True)>
  83.     Public Shared Function GetDC(hWnd As IntPtr) As IntPtr
  84.  
  85.     End Function
  86.     <DllImport("user32.dll", ExactSpelling:=True)>
  87.     Public Shared Function ReleaseDC(hWnd As IntPtr, hDC As IntPtr) As Integer
  88.     End Function
  89.     <DllImport("gdi32.dll", ExactSpelling:=True, SetLastError:=True)>
  90.     Public Shared Function CreateCompatibleDC(hDC As IntPtr) As IntPtr
  91.  
  92.     End Function
  93.     <DllImport("gdi32.dll", ExactSpelling:=True, SetLastError:=True)>
  94.     Public Shared Function DeleteDC(hdc As IntPtr) As Bool
  95.  
  96.     End Function
  97.     <DllImport("gdi32.dll", ExactSpelling:=True)>
  98.     Public Shared Function SelectObject(hDC As IntPtr, hObject As IntPtr) As IntPtr
  99.  
  100.     End Function
  101.     <DllImport("gdi32.dll", ExactSpelling:=True, SetLastError:=True)>
  102.     Public Shared Function DeleteObject(hObject As IntPtr) As Bool
  103.  
  104.     End Function
  105. End Class
  106.  
  107. Public MustInherit Class PerPixelAlphaForm
  108.     Inherits Form
  109.  
  110.     Public Sub New()
  111.         FormBorderStyle = FormBorderStyle.None
  112.     End Sub
  113.     Public Overloads Sub SetBitmap(bmp As Bitmap)
  114.         SetBitmap(bmp, 255)
  115.     End Sub
  116.     Protected Overrides ReadOnly Property CreateParams() As CreateParams
  117.         Get
  118.             Dim cp As CreateParams = MyBase.CreateParams
  119.             cp.ExStyle = cp.ExStyle Or &H80000
  120.             Return cp
  121.  
  122.  
  123.  
  124.         End Get
  125.     End Property
  126.     Public Overloads Sub SetBitmap(bmp As Bitmap, Opacity As Byte)
  127.  
  128.         If bmp.PixelFormat <> PixelFormat.Format32bppArgb Then
  129.             Throw New ApplicationException("The Bitmap must be a 32bpp with a Alpha Channel")
  130.         End If
  131.  
  132.         ‘Create Compatible DC with the screem
  133.         ‘Select bitmap with 32bpp with alpha into the compatible DC
  134.         ‘call UpdateLayeredWindow
  135.  
  136.         Dim ScreenDC As IntPtr = Win32.GetDC(IntPtr.Zero)
  137.         Dim MemDC As IntPtr = Win32.CreateCompatibleDC(ScreenDC)
  138.         Dim hBitmap As IntPtr = IntPtr.Zero
  139.         Dim oldBitmap As IntPtr = IntPtr.Zero
  140.         Try
  141.             hBitmap = bmp.GetHbitmap(Color.FromArgb(0))
  142.             oldBitmap = Win32.SelectObject(MemDC, hBitmap)
  143.             Dim thesize As Win32.Size = New Win32.Size(bmp.Width, bmp.Height)
  144.             Dim pointSource As Win32.Point = New Win32.Point(0, 0)
  145.             Dim topPos As Win32.Point = New Win32.Point(Left, Top)
  146.             Dim blend As Win32.BLENDFUNCTION = New Win32.BLENDFUNCTION()
  147.             blend.BlendOp = Win32.AC_SRC_OVER
  148.             blend.BlendFlags = 0
  149.             blend.SourceConstantAlpha = Opacity
  150.             blend.AlphaFormat = Win32.AC_SRC_ALPHA
  151.             Win32.UpdateLayeredWindow(Handle, ScreenDC, topPos, New Win32.Size(Size.Width, Size.Height), MemDC, pointSource, 0, blend, Win32.ULW_ALPHA)
  152.  
  153.         Catch ex As Exception
  154.  
  155.         Finally
  156.             Win32.ReleaseDC(IntPtr.Zero, ScreenDC)
  157.             If Not hBitmap = IntPtr.Zero Then
  158.                 Win32.SelectObject(MemDC, oldBitmap)
  159.                 Win32.DeleteObject(hBitmap)
  160.             End If
  161.             Win32.DeleteDC(MemDC)
  162.  
  163.         End Try
  164.  
  165.  
  166.     End Sub
  167. End Class
  168.  
  169.  

This provides the core implementation. The “Win32″ class here provides the needed API declarations.

In order to use this, we need to make our form derive from it, and then use the inherited SetBitmap function:

  1.  
  2. Public Class Form1
  3.     Inherits PerPixelAlphaForm
  4.     Private useBackground As Bitmap
  5.     Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
  6.         useBackground = New Bitmap("D:\pngtest.png")
  7.         SetBitmap(useBackground)
  8.     End Sub
  9. End Class
  10.  
  11.  

(Here I just used an image on my second Hard disk that had a transparency channel, but the Bitmap constructor parameter can easily be changed.). The result:

The code in action

The code in action:

The Project I used for this can be downloaded from here . This was created using Visual Studio Professional 2012, Update 1- other editions or earlier versions may have problems with the project or source files.

1,002 total views, 4 views today

Posted By: BC_Programming
Last Edit: 20 Jan 2013 @ 08:17 PM

EmailPermalinkComments (0)
Tags
 19 Jan 2013 @ 6:25 AM 

Though I do tend to try to write my samples and test applications, as well as any new programs, using Visual Studio 2012, I haven’t yet migrated most of my other applications to it. For BASeBlock and BCJobClock, for example, they started off in Visual Studio 2008. More recently, I migrated them to Visual Studio 2010. BCJobClock had it’s project upgraded to Visual Studio 2012, (but for some reason the admin applet doesn’t work on Windows 8, which is something that certainly bears further investigation). Anyway, I’ve been strongly considering it the more I think about it. In particular, I’ve found Visual Studio 2010 to actually be a lot slower. Originally, I thought this was because my 201 install had several add-ins installed, such as ReSharper, but now that I also have a version of ReSharper that works with Visual Studio 2012, I still find 2012 to be far more responsive.

Now VS2012 has gotten some flak from certain users for adopting the Windows 8 UI style into it’s icons, as well as using Caps in it’s menus. I really have no strong preference here at all, and I personally don’t see what the fuss is about. I’ve heard people say that the capitals “hurt their eyes” but I can honestly say that I don’t understand how that could be the case.

Anyway: I’ve been considering switching BASeBlock over the Visual Studio 2012. If I do I won’t be upgrading the project to use the 4.5 framework, though. At least not yet.

262 total views, no views today

Posted By: BC_Programming
Last Edit: 19 Jan 2013 @ 06:25 AM

EmailPermalinkComments (0)
Tags
Tags: , , ,
Categories: Programming
 18 Jan 2013 @ 11:53 PM 

Undo/Redo Stacks

The BASeBlock Editor has had an Undo/Redo stack for quite a while. The implementation of this logic is relatively simple, but the implementation- or rather, my recent re-implementation- seems like a good subject for a blog post.

Basically, an Undo/Redo Stack Let’s your Program reverse through changes that have been made, and then, if necessary, go forward through those changes. What makes this problem interesting is that, by and large, the core logic is really quite similar. I will attempt to outline the process of creating a Generic Undo/Redo Object that can be used in many contexts.

First, we’ll start with The abstract base class that we will use to represent Undo Elements:

  1.  
  2.     public abstract class UndoRedoStackItem
  3.     {
  4.         protected DateTime _ItemTime;
  5.         protected String _Description;
  6.  
  7.         public DateTime ItemTime { get { return _ItemTime; }}
  8.         public String Description { get { return _Description; }  }
  9.        
  10.         ///  <summary>
  11.         /// Constructs this object, giving it the appropriate Description.
  12.         ///  </summary>
  13.         ///  <param name="Description"/> Description for the constructed instance
  14.         protected UndoRedoStackItem(String Description)
  15.         {
  16.             _Description = Description;
  17.             _ItemTime = DateTime.Now;
  18.  
  19.         }
  20.         ///  <summary>
  21.         /// Copy constructor. This should be implemented by derived classes.
  22.         ///  </summary>
  23.         ///  <param name="copythis"/> Item to copy.
  24.         protected UndoRedoStackItem(UndoRedoStackItem copythis)
  25.         {
  26.             _ItemTime = copythis.ItemTime;
  27.             _Description = copythis.Description;
  28.             _ItemTime = copythis.ItemTime;
  29.         }
  30.         ///  <summary>
  31.         /// Creates a Deep Clone of this Object.
  32.         ///  </summary>
  33.         ///  <returns> A new instance of the same type, with appropriately deep-copied instances for all it’s instance data. </returns>
  34.         public abstract UndoRedoStackItem DeepClone();
  35.        
  36.     }
  37.  

Since we don’t know what, specifically, is being handled, we use this abstract class and provide only very basic methods. The DateTime can be used on appropriate menus or as a sort key, and the Description can be used for any menu text, or other UI elements as needed by the app consuming the class.

This will be used for a generic class, which I will call UndoRedoManager. This will, unsurprisingly, manage the undo and redo operations, or, more specifically, it will manage the data structures dealing with the Undo and Redo information. In order to actually undo, we will need to delegate the task to the caller, on the assumption that they know more about the StackItem. We will call the Events HandleRedo and HandleUndo, and they will take a simple EventArgs. First, we will define the EventArgs class definition.

  1.  
  2. class UndoRedoEventArgs<T>:EventArgs where T:UndoRedoStackItem
  3.     {
  4.         public T StackElement;
  5.         public Boolean Cancel = false;
  6.         public UndoRedoEventArgs(T stackelement)
  7.         {
  8.             StackElement = stackelement;
  9.         }
  10.  
  11.  
  12.     }
  13.  

The Event Argument class is relatively simple; we just have a field for the StackElement, and a field for Cancel, which we will deal with when we fire the event. We use a generic class because we need to support the management of any class type that derives from UndoRedoStackItem, where the appropriate application-specific data will be dealt with and stored.

The “UndoRedoManager” class we will create will be designed as generically as possible. And, to be honest, my original implementation will be a naive one, each Stack Element will be designated as storing a complete “state” for whatever the application is doing. A better approach for applications that have a large amount of state data is to instead store the changes, rather than the entire thing, but that sort of extra functionality is best discussed and designed after we have the basic framework in place.

The first step is to designate what we need to keep track of in the ‘Manager’ Class, as well as our events.

  1.  
  2. private int _maxsize = 10;
  3. //Stack of Undo Elements
  4. private Stack <t>  _UndoStack = new Stack </t>  <t> ();
  5. //stack of Redo Elements
  6. private Stack </t>  <t>  _RedoStack = new Stack </t>  <t> ();
  7. //events.
  8. public event EventHandler <undoredoeventargs <T> > UndoEvent;
  9. public event EventHandler </undoredoeventargs>  <undoredoeventargs <T> > RedoEvent;
  10.  </undoredoeventargs>  </t>  

We need a Maximum size, otherwise it’s possible for the stack to fill up with old Undo elements. We keep a stack for Undo as well as Redo elements. The actual public functionality we need to implement is a method to Undo, a Method to Redo, and a Method to “Push” a new element onto the Undo stack (register a change).

We’ll start with the first method that will usually be used: PushUndo. This will accept a parameter that is the type of the generic type parameter. It will need to:

  1. Make a Deep copy of the item being pushed.
  2. Push that deep copy onto the Undo Stack
  3. Trim the stack to the maximum size.
  4. Clear the Redo Stack

Here is the code to do that. TrimStack() is private method who’s implementation I will cover shortly:

  1.  
  2. public void PushUndo(T pushitem)
  3. {
  4.     Debug.Print("Undo Pushed…");
  5.     T pushthis = pushitem.DeepClone() as T;
  6.     _UndoStack.Push(pushthis);
  7.     TrimStack(_UndoStack, _maxsize);
  8.     _RedoStack.Clear();
  9. }
  10.  

Most of this is self-explanatory. TrimStack’s implementation is a bit trickier, since the Stack class is a bit less revealing beneath it’s Clothing, but we can seduce it:

  1.  
  2. private static void TrimStack<TStackType>(Stack<TStackType> stacktotrim, int maxelements)
  3. {
  4.     if (stacktotrim.Count < maxelements) return; //nothing to do…
  5.     Stack<TStackType> pushto = new Stack<TStackType>();
  6.     while (stacktotrim.Count > 0 && pushto.Count < maxelements)
  7.         pushto.Push(stacktotrim.Pop());
  8.     stacktotrim.Clear();
  9.     while (pushto.Count > 0)
  10.         stacktotrim.Push(pushto.Pop());
  11. }
  12.  

TrimStack here is written to take any Stack Type, though, arguably, this isn’t necessary in this current implementation. (No reason, however, to make it more specific, in my opinion)

First, if the stack has fewer elements than the passed maximum, we have no work to do, so we return right off the bat. Making our work quite easy.

If the Stack does have more elements than the maximum, we pop elements until either the stack to trim is empty (for some reason) or the temporary stack has maxelements elements.

The effect here is to grab the top maxelements items. After this, we clear the stack and push the elements we popped.

The task of performing the Undo has the following steps:

  1. If CanUndo returns false, return only null.
  2. Otherwise, Peek at the top element from the UndoStack.
  3. Create a new instance of the EventArgs class with the peeked element.
  4. Fire the Undo event with the created EventArgs.
  5. If the Event’s Cancel field has not been set, perform a Pop on the Undo Stack, and Push the item we retrieved earlier to the Redo Stack.
  6. Return the Item we removed

The idea here is that the Event handler that is tied to the class will do the application-specific activity for the “undo” operation- we don’t know what the data is, nor what it represents, but the program using us will, so we leave them to it. This also enables the less naive implementation concept that I’ll be using later to extend this.

  1.  
  2. public T Undo()
  3. {
  4.     if (CanUndo)
  5.     {
  6.         //pop element of UndoStack.
  7.         T popped = _UndoStack.Peek();
  8.         //fire Undo…
  9.         var useargs = new UndoRedoEventArgs<T>(popped);
  10.         fireUndo(useargs);
  11.         //if it wasn’t cancelled, really pop it off the stack, and push it to the Redo Stack.
  12.         if(!useargs.Cancel){
  13.             _UndoStack.Pop();
  14.             _RedoStack.Push(popped);
  15.         }
  16.         return popped;
  17.     }
  18.  
  19.     return null;
  20.  
  21. }
  22.  
  23.  
  24. Redo is, of course, very much the opposite-
  25.  <ol>
  26.  <li> If we cannot Redo, return null. </li>
  27.  <li> peek and store the first element of the Redo Stack. </li>
  28.  <li> Create a new UndoRedoEventArgs instance with the peeked element. </li>
  29.  <li> fire the Redo Event with the created instance. </li>
  30.  <li> if the passed argument‘s cancel field has not changed, pop the element from the redo stack, and push it onto the Undo stack. </li>
  31. </ol>
  32.  
  33.  
  34.  
  1.  
  2. public T Redo()
  3. {
  4.  
  5.     if (CanRedo)
  6.     {
  7.         T popped = _RedoStack.Peek();
  8.         //fire redo…
  9.         var useargs = new UndoRedoEventArgs<T>(popped);
  10.         fireRedo(useargs);
  11.         if (!useargs.Cancel)
  12.         {
  13.             _RedoStack.Pop();
  14.             _UndoStack.Push(popped);
  15.         }
  16.         return popped;
  17.  
  18.     }
  19.     return null;
  20. }
  21.  

And that is pretty much the core implementation. Of course, as it is, we don’t actually have an implementation for the StackElement class. Since that is something we left up to the client application, let’s create one. Here is a small Windows Form that utilizes the aforementioned classes as well as providing an implementation of the Stack Item for a TextBox:

The Designer class:

  1.  
  2.     partial class Form1
  3.     {
  4.         ///  <summary>
  5.         /// Required designer variable.
  6.         ///  </summary>
  7.         private System.ComponentModel.IContainer components = null;
  8.  
  9.         ///  <summary>
  10.         /// Clean up any resources being used.
  11.         ///  </summary>
  12.         ///  <param name="disposing"/> true if managed resources should be disposed; otherwise, false.
  13.         protected override void Dispose(bool disposing)
  14.         {
  15.             if (disposing && (components != null))
  16.             {
  17.                 components.Dispose();
  18.             }
  19.             base.Dispose(disposing);
  20.         }
  21.  
  22.         #region Windows Form Designer generated code
  23.  
  24.         ///  <summary>
  25.         /// Required method for Designer support – do not modify
  26.         /// the contents of this method with the code editor.
  27.         ///  </summary>
  28.         private void InitializeComponent()
  29.         {
  30.             this.textBox1 = new System.Windows.Forms.TextBox();
  31.             this.cmdUndo = new System.Windows.Forms.Button();
  32.             this.cmdRedo = new System.Windows.Forms.Button();
  33.             this.SuspendLayout();
  34.             //
  35.             // textBox1
  36.             //
  37.             this.textBox1.Location = new System.Drawing.Point(12, 30);
  38.             this.textBox1.Multiline = true;
  39.             this.textBox1.Name = "textBox1";
  40.             this.textBox1.Size = new System.Drawing.Size(490, 284);
  41.             this.textBox1.TabIndex = 0;
  42.             //
  43.             // cmdUndo
  44.             //
  45.             this.cmdUndo.Location = new System.Drawing.Point(12, 1);
  46.             this.cmdUndo.Name = "cmdUndo";
  47.             this.cmdUndo.Size = new System.Drawing.Size(75, 23);
  48.             this.cmdUndo.TabIndex = 1;
  49.             this.cmdUndo.Text = "Undo";
  50.             this.cmdUndo.UseVisualStyleBackColor = true;
  51.             this.cmdUndo.Click += new System.EventHandler(this.button1_Click);
  52.             //
  53.             // cmdRedo
  54.             //
  55.             this.cmdRedo.Location = new System.Drawing.Point(93, 1);
  56.             this.cmdRedo.Name = "cmdRedo";
  57.             this.cmdRedo.Size = new System.Drawing.Size(75, 23);
  58.             this.cmdRedo.TabIndex = 2;
  59.             this.cmdRedo.Text = "Redo";
  60.             this.cmdRedo.UseVisualStyleBackColor = true;
  61.             this.cmdRedo.Click += new System.EventHandler(this.button2_Click);
  62.             //
  63.             // Form1
  64.             //
  65.             this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
  66.             this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
  67.             this.ClientSize = new System.Drawing.Size(506, 318);
  68.             this.Controls.Add(this.cmdRedo);
  69.             this.Controls.Add(this.cmdUndo);
  70.             this.Controls.Add(this.textBox1);
  71.             this.Name = "Form1";
  72.             this.Text = "Form1";
  73.             this.Load += new System.EventHandler(this.Form1_Load);
  74.             this.ResumeLayout(false);
  75.             this.PerformLayout();
  76.  
  77.         }
  78.  
  79.         #endregion
  80.  
  81.         private System.Windows.Forms.TextBox textBox1;
  82.         private System.Windows.Forms.Button cmdUndo;
  83.         private System.Windows.Forms.Button cmdRedo;
  84.     }
  85.  

Proper code-behind class:

  1.  
  2.     public partial class Form1 : Form
  3.     {
  4.         TextBoxUndoManager tboxManager;
  5.         public Form1()
  6.         {
  7.             InitializeComponent();
  8.         }
  9.  
  10.         private void Form1_Load(object sender, EventArgs e)
  11.         {
  12.             tboxManager = new TextBoxUndoManager(textBox1, 50, 500);
  13.         }
  14.  
  15.         private void button1_Click(object sender, EventArgs e)
  16.         {
  17.             //undo
  18.             tboxManager.Undo();
  19.         }
  20.  
  21.         private void button2_Click(object sender, EventArgs e)
  22.         {
  23.             tboxManager.Redo();
  24.             //redo
  25.         }
  26.     }
  27.     public class TextBoxUndoManager
  28.     {
  29.         private int _DelayTime;
  30.         private TextBox _ManageBox = null;
  31.         private UndoRedoManager<TextUndoItem> UndoObject = null;
  32.         private Thread pressdelaythread = null;
  33.         private DateTime? StartDelay;
  34.         public TextBoxUndoManager(TextBox managebox, int nMaxSize,int msdelay)
  35.         {
  36.             UndoObject = new UndoRedoManager<TextUndoItem>(nMaxSize);
  37.             UndoObject.UndoEvent += UndoObject_UndoEvent;
  38.             UndoObject.RedoEvent += UndoObject_UndoEvent;
  39.             _DelayTime = msdelay;
  40.             _ManageBox = managebox;
  41.            
  42.             _ManageBox.KeyPress += _ManageBox_KeyPress;
  43.         }
  44.  
  45.      
  46.  
  47.         void UndoObject_UndoEvent(object sender, UndoRedoEventArgs<TextUndoItem> e)
  48.         {
  49.             _ManageBox.Text = e.StackElement.Text;
  50.             _ManageBox.SelectionStart = e.StackElement.SelectionStart;
  51.             _ManageBox.SelectionLength = e.StackElement.SelectionLength;
  52.         }
  53.  
  54.         void _ManageBox_KeyPress(object sender, KeyPressEventArgs e)
  55.         {
  56.  
  57.             StartDelay = DateTime.Now;
  58.             Debug.Print("StartDelay set to " + StartDelay);
  59.             if (pressdelaythread == null)
  60.             {
  61.                 //if it’s null, we are waiting for input, so we will push here too.
  62.                 UndoObject.PushUndo(new TextUndoItem(_ManageBox.Text, _ManageBox.SelectionStart, _ManageBox.SelectionLength, "Edit Text"));
  63.                 pressdelaythread = new Thread(DelayThread);
  64.                 pressdelaythread.Start();
  65.             }
  66.         }
  67.         private void DelayThread()
  68.         {
  69.             while(true){
  70.                 Thread.Sleep(0);
  71.                
  72.                 if((DateTime.Now-StartDelay).Value.Milliseconds > _DelayTime)
  73.                 {
  74.                     Debug.Print("Timeout expired");
  75.                     _ManageBox.Invoke((MethodInvoker)(() =>
  76.                     {
  77.                         _ManageBox.ClearUndo();
  78.                         UndoObject.PushUndo(new TextUndoItem(_ManageBox.Text, _ManageBox.SelectionStart, _ManageBox.SelectionLength, "Edit Text"));
  79.  
  80.                         pressdelaythread = null;
  81.                     }));
  82.                     return;
  83.                 }
  84.             }
  85.         }
  86.         public void Undo()
  87.         {
  88.             UndoObject.Undo();
  89.            
  90.  
  91.  
  92.         }
  93.         public void Redo()
  94.         {
  95.             UndoObject.Redo();
  96.  
  97.         }
  98.  
  99.  
  100.     }
  101.     public class TextUndoItem : UndoRedoStackItem
  102.     {
  103.         private String _Text;
  104.         private int _SelectionStart;
  105.         private int _SelectionLength;
  106.         public String Text { get { return _Text; } set { _Text = value; } }
  107.         public int SelectionStart { get { return _SelectionStart; } set { _SelectionStart = value; } }
  108.         public int SelectionLength { get { return _SelectionLength; } set { _SelectionLength = value; } }
  109.  
  110.         public TextUndoItem(String pText,int pStart,int pLength,String Description):base(Description)
  111.         {
  112.             _Text = pText;
  113.             _SelectionStart = pStart;
  114.             _SelectionLength = pLength;
  115.  
  116.         }
  117.  
  118.         public TextUndoItem(TextUndoItem clonethis)
  119.             : base(clonethis)
  120.         {
  121.  
  122.             _Text = (string) clonethis.Text.Clone();
  123.  
  124.         }
  125.         public override UndoRedoStackItem DeepClone()
  126.         {
  127.             return new TextUndoItem(this);
  128.         }
  129.        
  130.  
  131.     }
  132.  

In the above implementation, TextUndoItem is the UndoRedoStackItem implementation I created for textboxes; this stores the selection start and length as well as the full text. The Actual Undo implementation was less trivial than I had hoped; in this case I created a “Managing” class that uses the UndoRedoManager specifically with Textboxes, hooking the appropriate textbox events and implementing a delay after typing stops before Undo’s are pushed onto the stack. This is a very simple implementation of this particular class design; BASeBlock uses a very similar class in it’s Editor, but for the far more complex structures dealt with there, which include several lists of objects.

The extension and addition to this design that I mentioned earlier consists of storing not the entire state, but rather what changed from the previous element. This is unlikely to be a trivial thing to implement.

740 total views, no views today

Posted By: BC_Programming
Last Edit: 18 Jan 2013 @ 11:54 PM

EmailPermalinkComments (0)
Tags
 01 Jan 2013 @ 4:25 PM 

This is not another entry into the series regarding anagrams, but a much simpler synopsis using a very basic algorithm. The performance of programming languages and technologies are cited by a lot of people as being “slow” or “faster” or any number of terms of the sort. Recently, I’ve been told that Flash/ActionScript is “slow”. Now, I am not doing this to prove that wrong- in fact I think the results may prove that to be the case- but rather to show something that has been repeated several times by others.

First, the algorithm. In order to keep things simple, we’ll make the algorithm simple as well- it will simply generate a random number a million times and put it into an array or list.

The ActionScript version. This is ActionScript 2.0 since I only have Flash 8 installed:

  1.  
  2. onClipEvent (load) {
  3.     var t0:Number = getTimer();
  4. var myArray:Array = new Array();
  5.         for (var i:Number = 0; i < 1000000; i++)
  6.             myArray.push(Math.random());
  7. var t1:Number = getTimer();
  8. trace("Time Elapsed: " + String(t1 – t0));
  9. }
  10.  

Elapsed time was 7586 milliseconds (or 7.5s).

Now, to another language: let’s go with python for the moment.

  1.  
  2. import random
  3. import time
  4. startc = time.clock()
  5. arr =  []
  6. for i in range(0,1000000):
  7.     arr=arr +  [random.random()]
  8. endc = time.clock()
  9. print("time:", endc-startc)
  10.  

This doesn’t even finish in 10 minutes. Clearly we’ve proven that Python is really slow, correct? Not really, no:

  1.  
  2. import random
  3. import time
  4. startc = time.clock()
  5. arr =  []
  6. for i in range(0,1000000):
  7.     arr.append(random.random())
  8. endc = time.clock()
  9. print("time:", endc-startc)
  10.  

The reason the previous one was slow was because of how Python works. The line arr = arr + [random.random()] was allocating a new list and assigning it to the list. The old one was freed for garbage collection. The big problem was that as it went on those allocations got larger and larger. The above uses the append() method of the list, which adds it to the end of the same list- rather than creating a new one each time. The resulting execution time? 340 milliseconds or so.

OK, let’s move on to C:

  1.  
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <windows.h>
  5. #define NUMELEMENTS 1000000
  6. int main(int argc,char** args)
  7. {
  8.  int time_spent;
  9.     int begin = GetTickCount();
  10.  
  11.     int* randresults = (int*)malloc(NUMELEMENTS*sizeof(int));
  12.     for(int i=0;i<NUMELEMENTS-1;i++)
  13.     {
  14.         randresults [i]  = rand() / (double)RAND_MAX;
  15.     }
  16.     printf("test");
  17.     int end = GetTickCount();
  18.     time_spent = (end – begin);
  19.     printf("Time: %d",time_spent);
  20.     free(randresults);
  21.         return 0;
  22.  
  23. }
  24.  

This one is a bit messy since I couldn’t get the clock() stuff working, it always gave me a negative value, so I just included windows.h and used GetTickCount() instead. An interesting side-note is that I originally declared the array of int’s statically, as in:

  1. int randresults [NUMELEMENTS]  

Hilariously, though- that failed catastrophically, causing a StackOverflowException in the run-time itself when the program started. I had to switch it to dynamic allocation as shown above. The error makes sense since locals are normally stored on the stack; using malloc() puts them on the heap instead. Unsurprisingly, this implementation results in a run-time of 34 milliseconds.

What do we conclude? Well, first, it’s important to realize that C is simply less maintainable than Most other languages; this means that the “faster” implementation is going to take quite a bit longer to write, and it’s going to be more effort to maintain as well as add features too. Additionally, by virtue of it leaving far more responsibility in the hands of the programmer, it is more likely for bugs to creep in. Various controls, such as code reviews and standards can mitigate these concerns, but they cannot eliminate them completely. My point is that using C over a high-level language is not a magic bullet for a faster application, but requires more programmer time in terms of writing and maintaining the code to begin with, and is additionally more susceptible to bugs through that maintenance. In this instance, we are looking at over 34 times the speed. But, the only important concern is whether that speed difference matters. Another thing is that the Python implementation could likely be made even faster too- I didn’t fully explore that; either through code changes, or through the use of another python interpreter or compiler technology. Basically unless speed is actually an issue and it can be traced directly to the chosen language platform- and there is no way to mitigate the problem- does it make sense to choose a language like C, or even C++.

504 total views, 2 views today

Posted By: BC_Programming
Last Edit: 01 Jan 2013 @ 04:25 PM

EmailPermalinkComments (0)
Tags

 Last 50 Posts
 Back
Change Theme...
  • Users » 861
  • Posts/Pages » 192
  • Comments » 67
Change Theme...
  • VoidVoid « Default
  • LifeLife
  • EarthEarth
  • WindWind
  • WaterWater
  • FireFire
  • LightLight

PP



    No Child Pages.

Windows optimization tips



    No Child Pages.