More servicesWindows Live
HomeHotmailSpacesOneCare
 
MSN
Sign in
 
 
Spaces home  The House of Software En...PhotosProfileFriendsMore Tools Explore the Spaces community

Public folders

Folders shared with the world

The House of Software Engineer

The new house is here. The old is there: http://fabiogaluppo.blogspot.com/
June 24

Two versions for Lock-Free Stack

 
The two codes below are implementations of lock-free stack structure.
The purpose is the same, but the first version can be ported easily to other OSes.
Performance benchmark is a lesson to the reader.
 
The raw C++ implementation. In C++0x we'll change Interlocked APIs to atomic operations:
 
template
<typename T>
struct
LockFreeStack
{
  LockFreeStack() : Head_( NULL ){}

  void Push( T& value )
  {
    PNODE node = new NODE( value );
    PNODE oldHead;

    do
    {
      node->Next = oldHead = Head_;
    }while( oldHead != reinterpret_cast<PNODE>( InterlockedCompareExchangePointer(
                                      reinterpret_cast<volatile PVOID*>(&Head_), node, oldHead )));
  }

  T Pop()
  {
    PNODE node;
    PNODE oldHead;

    do
    {
      oldHead = Head_;
    }while( oldHead != (node = reinterpret_cast<PNODE>( InterlockedCompareExchangePointer(
                                            reinterpret_cast<volatile PVOID*>(&Head_), Head_->Next, oldHead ))));

    T temp = node->Data;
    delete node;
    return temp;
  }

private
:
  typedef struct NODE_TAG
  {
    NODE_TAG( T value ) : Next(NULL), Data(value){}
    NODE_TAG* Next;
    T Data;
  } NODE, *PNODE;

  PNODE Head_;

  LockFreeStack( const LockFreeStack& ){}
  LockFreeStack& operator=( const LockFreeStack& ){}
};


Using a Windows API facility called Singly Linked Lists

template<typename T>
struct LockFreeStack
{
  LockFreeStack()
  {
    Head_ = new_aligned<SLIST_HEADER>();
    if( NULL == Head_ )
      throw "memory allocation failed";

    InitializeSListHead( Head_ );
  }

  ~LockFreeStack()
  {
    InterlockedFlushSList( Head_ );
  }

  void Push( T value )
  {
    Item_ = new_aligned<ITEM>();
    if( NULL == Item_ )
      throw "stack is full";

    Item_->Value = value;
    Entry_ = InterlockedPushEntrySList( Head_, &Item_->Entry );
  }

  T Pop()
  {
    PSLIST_ENTRY tempEntry = InterlockedPopEntrySList( Head_ );
    if( NULL == tempEntry )
      throw "stack is empty";

    Item_ = reinterpret_cast<PITEM>( tempEntry );
    T temp = Item_->Value;
    _aligned_free( tempEntry );
    return temp;
  }

private
:
  typedef struct ITEM_TAG
  {
    SLIST_ENTRY Entry;
    T Value;
  } ITEM, *PITEM;

  PSLIST_ENTRY Entry_;
  PSLIST_HEADER Head_;
  PITEM Item_;

  template <class M> M* new_aligned()
  {
    return reinterpret_cast<M*>(_aligned_malloc( sizeof(M), MEMORY_ALLOCATION_ALIGNMENT ));
  }

  LockFreeStack( const LockFreeStack& ){}
  LockFreeStack& operator=( const LockFreeStack& ){}
};

 
June 13

Samples from my Concurrency Talk at Seminário TempoReal C++ Portabilidade e Performance

  
Samples from my Concurrency Talk at Seminário TempoReal C++ Portabilidade e Performance:
The following code is a C++ port to one of my previous samples: MapReduce with Parallelspace
 
#include
<iostream>
#include
<fstream>
#include
<vector>
#include
<map>
#include
<string>
#include
<boost/thread/thread.hpp>
#include
<boost/thread/mutex.hpp>
#include
<boost/filesystem.hpp>
#include
<boost/function.hpp>
#include
<boost/algorithm/string.hpp>
 
using
namespace std;
using
namespace boost;
using
namespace boost::filesystem;
 
void
get_files( const path& directory, vector<path>& files )
{
  directory_iterator end_iter;
  for( directory_iterator iter( directory ); iter != end_iter; ++iter )
  {
    if( is_directory( iter->status() ) ) continue;
    files.push_back( iter->path() );
  }
}
 
int
get_ProcessorCount(){ return 2; }
 
class TaskExecutor
{
typedef function2<void, map<string, int>&, const map<string, int>&> ConsolidationFunctionType;
typedef function1<map<string, int>, const path&> CountWordsFunctionType;

public:
  TaskExecutor( vector<path>::const_iterator begin, vector<path>::const_iterator end, 
                      const CountWordsFunctionType countWords,
                      const ConsolidationFunctionType consolidation,
                      map<string, int>& result ) : Begin_( begin ), 
                      End_( end ),
                      CountWordsFunction_( countWords ),
                      ConsolidationFunction_( consolidation ),
                      Result_( result ){}

  void operator()()
  {
    for( vector<path>::const_iterator iter = Begin_; iter != End_; ++iter )
      ConsolidationFunction_( Result_, CountWordsFunction_( *iter ) );
  }
 
private
:
  vector<path>::const_iterator Begin_, End_;
  const ConsolidationFunctionType ConsolidationFunction_;
  const CountWordsFunctionType CountWordsFunction_;
  map<string, int>& Result_;
};
 
void
key_count( map<string, int>& dictionary, const string& word, int value )
{
  dictionary[ word ] = dictionary.end() != dictionary.find( word ) ? dictionary[ word ] + value : value;
}
 
map<string, int> map_function( const path& filename )
{
  map<string, int> wordCount;

  ifstream file;
  const int MAXLEN = 1024;
  char line[ MAXLEN ];

  file.open( filename.directory_string().c_str() ); 
 
  while( file.getline( line, MAXLEN ) )
  {
    vector<string> split_v;
    split( split_v, string( line ), is_any_of( " " ) );
    for( vector<string>::const_iterator iter = split_v.begin(); iter != split_v.end(); ++iter )
      key_count( wordCount, *iter, 1 );
  } 
 
  file.close();
  return wordCount;
}
 
void
reduce_function( map<string, int>& destination, const map<string, int>& source )
{
  for( map<string, int>::const_iterator iter = source.begin(); iter != source.end(); ++iter )
  key_count( destination, iter->first, iter->second );
}
 
void
wordcount_mapreduced( const vector<path>& files, map<string, int>& wordCount )
{
  //data partition
  int numberOfPartitions = get_ProcessorCount() * 2; //2 threads per core
  int numberOfFiles = static_cast<int>( files.size() );
  if( numberOfFiles < numberOfPartitions ) numberOfPartitions = numberOfFiles;
  int delta = numberOfFiles / numberOfPartitions;
  vector< map<string, int> > result( numberOfPartitions );
  thread_group tg;
  //for parallel
  for( int step = 0; step < numberOfPartitions; ++step )
  {
    vector<path>::const_iterator begin = files.begin() + delta * step,
    end = numberOfPartitions - 1 == step ? files.end() : files.begin() + delta * step + delta;
    //fork
    tg.create_thread( TaskExecutor( begin, end, map_function, reduce_function, result[step] ) );
  }
 
  //join
  tg.join_all();
  for( vector< map<string, int> >::const_iterator iter = result.begin(); iter != result.end(); ++iter )
    reduce_function( wordCount, *iter );
}
 
int
main()
{
  vector<path> files;
  get_files( "c:\\txttest\\", files );
  map<string, int> wordCount;

  wordcount_mapreduced( files, wordCount );

  for( map<string, int>::const_iterator iter = wordCount.begin(); iter != wordCount.end(); ++iter )
    cout << iter->first << " = " << iter->second << endl;
}
February 25

Get the size of directories from all drives with F#

 
This small F# utility uses recursion to inspect all directories from all drives installed (including network drives mapped).
The sizes are printed in the console screen (or could be redirected).
 
 
#light

open
System.IO
open System

let
ConvertTo (n:int64) (d:float) = n / Convert.ToInt64( d )
//let ConvertToMegabytes (n:int64) = ConvertTo n (1024.0 ** 2.0)
let ConvertToKilobytes (n:int64) = ConvertTo n 1024.0

let
rec getSizeOfDir (path:string) =
    let getSizeOfFiles (dir:string) =
        try
            DirectoryInfo(dir).GetFiles() |> Seq.sumByInt64( fun file -> file.Length )
        with
            | :? UnauthorizedAccessException -> 0L;

    try
        let size = (Directory.GetDirectories( path ) |> Seq.sumByInt64( fun dir -> getSizeOfDir( dir ) )) + getSizeOfFiles( path )
        printfn "Path = %s\r\nSize = %d KB (%d bytes)\r\n" path (ConvertToKilobytes size) size
        size
    with
        | :? UnauthorizedAccessException -> 0L
        | :? IOException -> 0L;

let main = 
    let sw = new Diagnostics.Stopwatch()
    let tm = DateTime.Now
    sw.Start()
    DriveInfo.GetDrives() |> Seq.iter( fun drv -> getSizeOfDir drv.Name |> ignore )
    sw.Stop()
    printfn "\r\n\r\nElapsed time = %s" (sw.Elapsed.ToString())
 
 
This utility could run better if reworked to support threads. Maybe next time... Com sono
 
February 07

XNA, Visual C++ and Guitar Hero


Is it possible to write XNA programs with Visual C++? Yes, it is! Someone show that is possible in F#, too.

The XNA Game Studio 2.0 can be installed inside Visual Studio 2005 Professional (the previous version is hosted only in VC# Express).

The sample below is a Guitar Hero Panel. You plug-in a guitar on PC, and press Fret buttons, Strum bar and Whammy bar to see the feedback. (This sample doesn´t have sounds, just visual feedback)

GHP
 
How can you do to write your own XNA programs with Visual C++?
 
1. Create a XNA Windows Game (or XNA Xbox 360 Game) project with C#. (C# will be the host of the C++/CLI dll. C# is necessary to compile Game Assets like images, fonts, ...)
2. Add a new project Visual C++ CLR Class Library into the current solution. The XNA program will be coded entirely in C++/CLI, here. Is very important (if you want to port to Xbox 360) to compile this project with /clr:safe switch. This ensure that the generated code is MSIL-only. Add reference to the assemblies: Microsoft.Xna.Framework.dll and Microsoft.Xna.Framework.Game.dll. They are at Microsoft XNA install dir something like: <XNA install dir>\XNA Game Studio\v2.0\References\Windows\x86\
3. Add a reference to the VC++ CLR DLL in the C# project. And call the game class written in C++/CLI, at Main method in C# code. (You even have the ability to debug step-by-step) Surpreso
 
The following code is the C++/CLI game program. If you look with attention you see that we have templates and stack semantics:
 
using namespace Microsoft::Xna::Framework;
using namespace Microsoft::Xna::Framework::Graphics;
using namespace Microsoft::Xna::Framework::Input;

namespace
GuitarHeroControlPanel
{

ref struct Piece
{
    Piece( Texture2D^ image, Vector2 position, SpriteBatch^ spriteBatch ) : 
    Display_( false ), Image_( image ), Position_( position ), SpriteBatch_( spriteBatch ){}

    void Update( bool displayStatus ){ Display_ = displayStatus; }
    void Draw()if( Display_ ) SpriteBatch_->Draw( Image_, Position_, Color::White ); }

private:
    bool Display_;
    Vector2 Position_;
    Texture2D^ Image_;
    SpriteBatch^ SpriteBatch_;
};

public ref class GuitarHeroControlPanel : Game
{
public:
    GuitarHeroControlPanel()
    {
        Graphics_ = gcnew GraphicsDeviceManager(this);
        Graphics_->PreferredBackBufferWidth = 1280;
        Graphics_->PreferredBackBufferHeight = 416;
        Window->Title = "Guitar Hero Panel by Fabio Galuppo. Implemented with XNA and Visual C++ 2005. Visit: http://www.gamecultura.com.br/. Blog: http://fabiogaluppo.spaces.live.com/";
        Content->RootDirectory = "Content";
}

private:
    template<class T> T^ CntLoad( System::String^ assetName ){ return Content->Load<T^>( assetName ); }
    template<PlayerIndex P> GamePadButtons GetButtons(){ return GamePad::GetState(P).Buttons; }
    template<PlayerIndex P> GamePadDPad GetDPad(){ return GamePad::GetState(P).DPad; }
    template<PlayerIndex P> GamePadThumbSticks GetThumbSticks(){ return GamePad::GetState(P).ThumbSticks; }
    bool IsPressed( ButtonState bs ){ return bs == ButtonState::Pressed; }

protected:
    virtual void LoadContent() override
    {
        SpriteBatch_ = gcnew SpriteBatch(GraphicsDevice);
        Font_ = CntLoad<SpriteFont>( "Tahoma" );
        GuitarTexture_ = CntLoad<Texture2D>( "guitarhero" );
        GCLogo_ = CntLoad<Texture2D>( "gclogo" );
        VCLogo_ = CntLoad<Texture2D>( "vclogo" );

        GreenFret_ = gcnew Piece( CntLoad<Texture2D>( "green" ), Vector2(965.0, 0.0), SpriteBatch_ );
        RedFret_ = gcnew Piece( CntLoad<Texture2D>( "red" ), Vector2(930.0, 0.0), SpriteBatch_ );
        YellowFret_ = gcnew Piece( CntLoad<Texture2D>( "yellow" ), Vector2(895.0, 0.0), SpriteBatch_ );
        BlueFret_ = gcnew Piece( CntLoad<Texture2D>( "blue" ), Vector2(858.0, 0.0), SpriteBatch_ );
        OrangeFret_ = gcnew Piece( CntLoad<Texture2D>( "orange" ), Vector2(821.0, 0.0), SpriteBatch_ );
        Strum_ = gcnew Piece( CntLoad<Texture2D>( "strum" ), Vector2(269.0, 0.0), SpriteBatch_ );
        Whammy_ = gcnew Piece( CntLoad<Texture2D>( "whammy" ), Vector2(0.0, 259.0), SpriteBatch_ );

        GCLogoVec_ = Vector2( 895.0 , 0.0 );
        VCLogoVecPos_ = Vector2( 250.0, 130.0 ); 
        VCLogoVecOri_ = Vector2( VCLogo_->Width / 2.0f, VCLogo_->Height / 2.0f );
        FontVec_ = Vector2( 880.0, 380.0 ); 
    }

    virtual void Update(GameTime^ gameTime) override 
    {
        if ( IsPressed( GetButtons<PlayerIndex::One>().Back ) ) Game::Exit();

        //Fret Buttons
        GreenFret_->Update( IsPressed( GetButtons<PlayerIndex::One>().A ) );
        RedFret_->Update( IsPressed( GetButtons<PlayerIndex::One>().B ) );
        YellowFret_->Update( IsPressed( GetButtons<PlayerIndex::One>().Y ) );
        BlueFret_->Update( IsPressed( GetButtons<PlayerIndex::One>().X ) );
        OrangeFret_->Update( IsPressed( GetButtons<PlayerIndex::One>().LeftShoulder ) );

        //Strum Bar
        Strum_->Update( IsPressed( GetDPad<PlayerIndex::One>().Up ) || IsPressed( GetDPad<PlayerIndex::One>().Down ) );

        //Whammy Bar
        Whammy_->Update( GetThumbSticks<PlayerIndex::One>().Right.X >= 0.0 );

        Game::Update(gameTime);
    }

    virtual void Draw(GameTime^ gameTime) override
    {
        Graphics_->GraphicsDevice->Clear(Color::CornflowerBlue);
        Game::Draw(gameTime);

        SpriteBatch_->Begin();

            SpriteBatch_->Draw( GuitarTexture_, Vector2::Zero, Color::White );

            GreenFret_->Draw();
            RedFret_->Draw();
            YellowFret_->Draw();
            BlueFret_->Draw();
            OrangeFret_->Draw();
            Strum_->Draw();

            Whammy_->Draw();

            SpriteBatch_->Draw( GCLogo_, GCLogoVec_, Color::White ); 

            SpriteBatch_->Draw( VCLogo_, VCLogoVecPos_, NullRect_, Color::White, -45.0, VCLogoVecOri_, 1.0, SpriteEffects::None, 0.0 );

            SpriteBatch_->DrawString( Font_, "http://fabiogaluppo.spaces.live.com/", FontVec_, Color::Black );

        SpriteBatch_->End();
    }

private:
    GraphicsDeviceManager^ Graphics_;
    SpriteBatch^ SpriteBatch_;
    Texture2D ^GuitarTexture_, ^GCLogo_, ^VCLogo_;
    Vector2 GCLogoVec_, VCLogoVecPos_, VCLogoVecOri_, FontVec_;
    System::Nullable<Rectangle> NullRect_;
    SpriteFont^ Font_;
    Piece ^GreenFret_, ^RedFret_, ^YellowFret_, ^BlueFret_, ^OrangeFret_, ^Strum_, ^Whammy_;
};

};
 
The C# host program:
 
using System;

namespace
GuitarHeroControlPanel
{

static class Program
{
    static void Main()
    {
        using (GuitarHeroControlPanel panel = new GuitarHeroControlPanel()) panel.Run();
    }
}

}
 
Do you like games? Stay tuned at GameCultura   
January 03

TechEd Brasil 2007 - TxF Demo #5

 
How to consume the TxF wrapper with C#:
 
using System;
using System.Transactions;
using System.IO;

class
Program
{
    static void Main(string[] args)
    {
        using (TransactionScope scope = new TransactionScope())
        {
            using (StreamWriter sw = new StreamWriter(NTFS.Transactional.File.OpenTransacted("c:\\ManagedNTFSTx.txt", FileMode.OpenOrCreate, FileAccess.Write, FileShare.None)))            
                for (int i = 0; i < 1000; ++i) sw.WriteLine("Hello World");

            scope.Complete(); //omit this line to rollback transaction 
        }

        using (TransactionScope scope = new TransactionScope())
        {
            NTFS.Transactional.File.CopyTransacted("c:\\ManagedNTFSTx.txt", "c:\\ManagedNTFSTxClone.txt", true);
           
            scope.Complete(); //omit this line to rollback transaction 
        }
    }
}

TechEd Brasil 2007 - TxF Demo #4

 
This managed wrapper is inspired/adapted/improved from this article.
It supports some NTFS transactional file operations like copy, delete, create and open. 
 
using
System;
using
System.IO;
using
System.Security;
using
System.Runtime.InteropServices;
using
System.Runtime.ConstrainedExecution;
using
System.Runtime.CompilerServices;
using
Microsoft.Win32.SafeHandles;
using
System.Transactions;

namespace
NTFS.Transactional
{
    [ComImport, Guid("79427A2B-F895-40e0-BE79-B57DC82ED231"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    interface IKernelTransaction
    {
        int GetHandle(out IntPtr pHandle);
    }

    [SuppressUnmanagedCodeSecurity]
    static class
WindowsAPI
    {
        [DllImport("kernel32.dll", SetLastError = true)]
        [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
        public static extern bool CloseHandle(IntPtr hObject);

        [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
        public static extern SafeFileHandle CreateFileTransacted
        (
            string lpFileName,
            Constants.FileAccess dwDesiredAccess,
            Constants.FileShare dwShareMode,
            IntPtr lpSecurityAttributes,
            Constants.FileMode dwCreationDisposition,
            int dwFlagsAndAttributes,
            IntPtr hTemplateFile,
            IntPtr hTransaction,
            IntPtr pusMiniVersion,
            IntPtr pExtendedParameter
        );

        [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
        public static extern bool CopyFileTransacted
        (
            string lpExistingFileName,
            string lpNewFileName,    
            IntPtr lpProgressRoutine,
            IntPtr lpData,    
            ref bool pbCancel,
            Constants.CopyFile dwCopyFlags,
            IntPtr hTransaction
        );

        [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
        public static extern bool DeleteFileTransacted
        (
            string file, IntPtr transaction
        );

        public static bool SUCCEDDED(int hr) { return hr == Constants.ERROR_SUCCESS; }

        public static void ThrowsLastError() { throw new System.ComponentModel.Win32Exception(Marshal.GetLastWin32Error()); }

        public static class
Constants
        {
            public const int ERROR_SUCCESS = 0x0;

            [Flags]
            public enum FileAccess
            {
                GENERIC_READ = unchecked((int)0x80000000),
                GENERIC_WRITE = 0x40000000
            }

            [Flags]
            public enum
FileShare
            {
                FILE_SHARE_NONE = 0x0,
                FILE_SHARE_READ = 0x1,
                FILE_SHARE_WRITE = 0x2,
                FILE_SHARE_DELETE = 0x4
            }

            public enum FileMode
            {
                CREATE_NEW = 0x1,
                CREATE_ALWAYS = 0x2,
                OPEN_EXISTING = 0x3,
                OPEN_ALWAYS = 0x4,
                TRUNCATE_EXISTING = 0x5
            }

            [Flags]
            public enum CopyFile
            {
                COPY_FILE_FAIL_IF_EXISTS = 0x1,
                COPY_FILE_RESTARTABLE = 0x2,
                COPY_FILE_OPEN_SOURCE_FOR_WRITE = 0x4,
                COPY_FILE_ALLOW_DECRYPTED_DESTINATION = 0x8,
                COPY_FILE_COPY_SYMLINK = 0x800
            }
        }
    }

    public static class File
    {
        public static void DeleteTransacted(string path)
        {
            using (KernelTransactionHandle transactionHandle = KernelTransactionHandle.Get())
                if (!WindowsAPI.DeleteFileTransacted(path, transactionHandle.DangerousGetHandle()))                
                    WindowsAPI.ThrowsLastError();
        }

        public static void CopyTransacted(string from, string to, bool overwrite)
        {
            using (KernelTransactionHandle transactionHandle = KernelTransactionHandle.Get())
            {
                bool cancel = false;
                if (!WindowsAPI.CopyFileTransacted
                        (
                            from,
                            to,
                            IntPtr.Zero,
                            IntPtr.Zero,
                            ref cancel,
                            overwrite ? 0 : WindowsAPI.Constants.CopyFile.COPY_FILE_FAIL_IF_EXISTS,
                            transactionHandle.DangerousGetHandle()
                        )
                )
                    WindowsAPI.ThrowsLastError();
            }
        }

        public static FileStream OpenTransacted(string path, FileMode mode, FileAccess access, FileShare share)
        {
            using (KernelTransactionHandle transactionHandle = KernelTransactionHandle.Get())
            {
                SafeFileHandle fileTransactedHandle = WindowsAPI.CreateFileTransacted
                                                                        (
                                                                            path,
                                                                            ToNativeFileAccess(access),
                                                                            ToNativeFileShare(share),
                                                                            IntPtr.Zero,
                                                                            ToNativeFileMode(mode),
                                                                            0,
                                                                            IntPtr.Zero,
                                                                            transactionHandle.DangerousGetHandle(),
                                                                            IntPtr.Zero,
                                                                            IntPtr.Zero
                                                                        );

                if (fileTransactedHandle.IsInvalid) 
                    WindowsAPI.ThrowsLastError();
                return new FileStream(fileTransactedHandle, access);
            }
        }

        static WindowsAPI.Constants.FileAccess ToNativeFileAccess(FileAccess access)
        {
            if (FileAccess.Read == access)
                return WindowsAPI.Constants.FileAccess.GENERIC_READ;
            else if (FileAccess.Write == access)
                return WindowsAPI.Constants.FileAccess.GENERIC_WRITE;
            return WindowsAPI.Constants.FileAccess.GENERIC_READ | WindowsAPI.Constants.FileAccess.GENERIC_WRITE;
        }

        static WindowsAPI.Constants.FileMode ToNativeFileMode(FileMode mode)
        {
            return (WindowsAPI.Constants.FileMode)(int)(FileMode.Append == mode ? FileMode.OpenOrCreate : mode);
        }

        static WindowsAPI.Constants.FileShare ToNativeFileShare(FileShare share)
        {
            return (WindowsAPI.Constants.FileShare)(int)share;
        }
    }

    public class KernelTransactionHandle :
SafeHandleZeroOrMinusOneIsInvalid
    {
        internal KernelTransactionHandle(IntPtr existingHandle) : this(existingHandle, true) { }
        internal KernelTransactionHandle(IntPtr existingHandle, bool ownsHandle) : base(true)
        {
            this.SetHandle(existingHandle);
        }

        protected override bool ReleaseHandle() { return WindowsAPI.CloseHandle(handle); }
       
        public static KernelTransactionHandle Get() { return Get(Transaction.Current); }
        public static KernelTransactionHandle Get(Transaction transaction)
        {
            if (null == transaction)
                throw new NullReferenceException();

            IKernelTransaction kernelTransaction = TransactionInterop.GetDtcTransaction(transaction) as IKernelTransaction;
            KernelTransactionHandle transactionHandler = null;

            RuntimeHelpers.PrepareConstrainedRegions();

            try { }
//CER Scope
            finally
            {
                IntPtr txHandle;
                int hr = kernelTransaction.GetHandle(out txHandle);

                if (!WindowsAPI.SUCCEDDED(hr))
                    throw new System.ComponentModel.Win32Exception(hr);
                transactionHandler = new KernelTransactionHandle(txHandle);
            }
//CER Scope

            return transactionHandler;
        }
    }
}
December 28

Web Page request asynchronously with Parallelspace

 
Today, I released the Parallelspace version 0.2. The following sample is a classic implementation of many threads requesting web pages.
This new version has a lot of new stuff like Async I/O operations via Begin/End methods. In this sample, AsyncUtil.WebRequestGetResponse is responsable to call the Async I/O operations.

using
System;
using
System.Threading;
using
System.Net;

using
Parallelspace;
using Parallelspace.Utilities;

class
WebRequestResponseAsyncSample
{
    private void UseProxy(WebRequest req, string proxyAddress, string user, string pwd)
    {
        WebProxy proxy = new WebProxy(proxyAddress);
        proxy.Credentials = new NetworkCredential(user, pwd);
        req.Proxy = proxy;
    }

    private void Display( string url, string content )
    {
        String line = new String('-', url.Length + 5);
        System.Text.StringBuilder sb = new System.Text.StringBuilder();
        sb.AppendFormat("{0}\r\n", line);
        sb.AppendFormat("url: {0}\r\n", url);
        sb.AppendFormat("thread id: {0}\r\n", Thread.CurrentThread.ManagedThreadId);
        sb.AppendFormat("{0}\r\n", line);
        sb.Append(content); 
        sb.AppendFormat("\r\n{0}\r\n", line);
        Console.WriteLine(sb.ToString());
    }

    public Future UrlGetAsync(Block block, string url)
    {
        return block.Run<DataWithWaitHandle<WebResponse, ManualResetEvent>>(
            delegate
            {
                try
                {
                    WebRequest req = WebRequest.Create(url);
                    //UseProxy(req, "proxy_address", "user", "password" );
                    return new DataWithWaitHandle<WebResponse, ManualResetEvent>
                        (
                            AsyncUtil.WebRequestGetResponse(req),
                            new ManualResetEvent(false)
                        );
                }
                catch (Exception e)
                {
                    Display(url, e.Message);
                    return new DataWithWaitHandle<WebResponse, ManualResetEvent>(null
                                    new ManualResetEvent(true));
                }
            },

            delegate(Future<DataWithWaitHandle<WebResponse, ManualResetEvent>> f)
            {
                DataWithWaitHandle<WebResponse, ManualResetEvent> value = f.Value;

                if (null != value.Data)
                    using (System.IO.StreamReader sr = new System.IO.StreamReader(value.Data.GetResponseStream()))
                        Display(url, sr.ReadToEnd().Substring(0, 1024)); 

                value.WaitHandle.Set();
            },

            url
        );
    }

    public void Run( params string[] urls )
    {
        if (null != urls && urls.Length > 0)
        {
            Future[] f = new Future[urls.Length];
            for (int i = 0; i < urls.Length; ++i)
                f[i] = UrlGetAsync(BlockRunner.Get(), urls[i]);
            WaitHandle.WaitAll(ConvertUtil.ToWaitHandleArray<WebResponse, ManualResetEvent>(f)); 
        }
    }
}

class
Program
{
    static void Main(string[] args)
    {
        //new WebRequestResponseAsyncSample().Run(args);

        new WebRequestResponseAsyncSample().Run(
                    "http://www.thisisnotsupposedtoexist.org/",
                    "http://www.live.com/",
                    "http://blogs.msdn.com/MSRoboticsStudio/",
                    "http://fabiogaluppo.spaces.live.com/",
                    "This isn't an URL"
            );
    }
}

 
A cool implementation in F# can be found in Don Syme's blog (the main designer of F#). Another implementation, using C