Boost logo

Boost-Commit :

From: xushiweizh_at_[hidden]
Date: 2008-05-06 09:49:00


Author: xushiwei
Date: 2008-05-06 09:48:59 EDT (Tue, 06 May 2008)
New Revision: 45169
URL: http://svn.boost.org/trac/boost/changeset/45169

Log:
lockfree stack
Added:
   sandbox/memory/boost/lockfree/
   sandbox/memory/boost/lockfree/stack.hpp (contents, props changed)
Binary files modified:
   sandbox/memory/libs/memory/bin/win32/boost-memory.dll
Text files modified:
   sandbox/memory/boost/detail/performance_counter.hpp | 4
   sandbox/memory/boost/detail/threadmodel.hpp | 4 +
   sandbox/memory/boost/detail/winapi/atomic/windows.hpp | 9 ++
   sandbox/memory/boost/memory/basic.hpp | 2
   sandbox/memory/boost/memory/system_alloc.hpp | 2
   sandbox/memory/boost/memory/system_pool.hpp | 120 +++++++++++++++++++++++++++++----------
   sandbox/memory/boost/memory/thread/tls.hpp | 2
   sandbox/memory/libs/memory/memory.def | 3 +
   sandbox/memory/libs/memory/memory.dsp | 29 +++++++++
   sandbox/memory/libs/memory/src/system_pool.cpp | 2
   sandbox/memory/libs/memory/test/test_basic/memory/performance.cpp | 7 +-
   sandbox/memory/libs/memory/test/test_basic/test.dsp | 4
   12 files changed, 144 insertions(+), 44 deletions(-)

Modified: sandbox/memory/boost/detail/performance_counter.hpp
==============================================================================
--- sandbox/memory/boost/detail/performance_counter.hpp (original)
+++ sandbox/memory/boost/detail/performance_counter.hpp 2008-05-06 09:48:59 EDT (Tue, 06 May 2008)
@@ -27,9 +27,9 @@
 template <class UIntT, class CharT>
 inline CharT* BOOST_DETAIL_CALL _ui2estr(UIntT val, CharT* estr)
 {
- *estr-- = '\0';
+ *estr = '\0';
         do {
- *estr-- = '0' + val % 10;
+ *--estr = '0' + val % 10;
                 val /= 10;
         }
         while (val);

Modified: sandbox/memory/boost/detail/threadmodel.hpp
==============================================================================
--- sandbox/memory/boost/detail/threadmodel.hpp (original)
+++ sandbox/memory/boost/detail/threadmodel.hpp 2008-05-06 09:48:59 EDT (Tue, 06 May 2008)
@@ -24,7 +24,9 @@
 
 // -------------------------------------------------------------------------
 
-#include "winapi/winbase.h"
+#ifndef BOOST_DETAIL_WINAPI_WINBASE_H
+#include <boost/detail/winapi/winbase.h>
+#endif
 
 #ifndef BOOST_DETAIL_THREADMODEL_SINGLE_THREAD_HPP
 #include "threadmodel/single_thread.hpp"

Modified: sandbox/memory/boost/detail/winapi/atomic/windows.hpp
==============================================================================
--- sandbox/memory/boost/detail/winapi/atomic/windows.hpp (original)
+++ sandbox/memory/boost/detail/winapi/atomic/windows.hpp 2008-05-06 09:48:59 EDT (Tue, 06 May 2008)
@@ -39,8 +39,15 @@
                 (PVOID*)Destination, (PVOID)Exchange, (PVOID)Comperand);
 }
 
+__forceinline PVOID WINAPI boost_InterlockedCompareExchangePointer(
+ PVOID* Destination, PVOID Exchange, PVOID Comperand)
+{
+ return InterlockedCompareExchange(
+ Destination, Exchange, Comperand);
+}
+
 #define InterlockedCompareExchange boost_InterlockedCompareExchange
-#define InterlockedCompareExchangePointer InterlockedCompareExchange
+#define InterlockedCompareExchangePointer boost_InterlockedCompareExchangePointer
 
 #elif !defined(InterlockedCompareExchangePointer)
 

Added: sandbox/memory/boost/lockfree/stack.hpp
==============================================================================
--- (empty file)
+++ sandbox/memory/boost/lockfree/stack.hpp 2008-05-06 09:48:59 EDT (Tue, 06 May 2008)
@@ -0,0 +1,134 @@
+//
+// boost/lockfree/stack.hpp
+//
+// Copyright (c) 2004 - 2008 xushiwei (xushiweizh_at_[hidden])
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org/libs/lockfree/todo.htm for documentation.
+//
+#ifndef BOOST_LOCKFREE_STACK_HPP
+#define BOOST_LOCKFREE_STACK_HPP
+
+#ifndef BOOST_DETAIL_DEBUG_HPP
+#include <boost/detail/debug.hpp>
+#endif
+
+#ifndef BOOST_DETAIL_WINAPI_WINBASE_H
+#include <boost/detail/winapi/winbase.h>
+#endif
+
+// -------------------------------------------------------------------------
+
+#ifndef NS_BOOST_LOCKFREE_BEGIN
+#define NS_BOOST_LOCKFREE_BEGIN namespace boost { namespace lockfree {
+#define NS_BOOST_LOCKFREE_END } }
+#define NS_BOOST_LOCKFREE boost::lockfree
+#endif
+
+#ifndef BOOST_LOCKFREE_CALL
+#define BOOST_LOCKFREE_CALL
+#endif
+
+NS_BOOST_LOCKFREE_BEGIN
+
+// -------------------------------------------------------------------------
+// class stack
+
+class stack
+{
+private:
+ stack(const stack&);
+ void operator=(const stack&);
+
+public:
+ class node
+ {
+ private:
+ node* m_prev;
+ friend class stack;
+
+ public:
+ node() : m_prev(NULL) {}
+ node* prev() const { return m_prev; }
+ };
+
+private:
+ node* m_top;
+
+public:
+ stack() : m_top(NULL)
+ {
+ }
+
+ void BOOST_LOCKFREE_CALL push(node* val)
+ {
+ BOOST_DETAIL_ASSERT(val->m_prev == NULL);
+
+ node* the_top = m_top;
+ for (;;)
+ {
+ val->m_prev = the_top;
+ node* the_top2 = (node*)
+ InterlockedCompareExchangePointer((PVOID*)&m_top, val, the_top);
+ if (the_top2 == the_top)
+ return;
+ the_top = the_top2;
+ }
+ }
+
+ node* BOOST_LOCKFREE_CALL clear()
+ {
+ return (node*)InterlockedExchangePointer((PVOID*)&m_top, NULL);
+ }
+
+ node* BOOST_LOCKFREE_CALL pop()
+ {
+ node* the_top = m_top;
+ for (;;)
+ {
+ if (the_top == NULL)
+ return NULL;
+ node* the_top2 = (node*)
+ InterlockedCompareExchangePointer((PVOID*)&m_top, the_top->m_prev, the_top);
+ if (the_top2 == the_top)
+ return the_top;
+ the_top = the_top2;
+ }
+ }
+};
+
+// -------------------------------------------------------------------------
+// class typed_stack
+
+template <class Type>
+class typed_stack
+{
+private:
+ stack m_impl;
+
+public:
+ void BOOST_LOCKFREE_CALL push(Type* val)
+ {
+ m_impl.push(val);
+ }
+
+ Type* BOOST_LOCKFREE_CALL clear()
+ {
+ return static_cast<Type*>(m_impl.clear());
+ }
+
+ Type* BOOST_LOCKFREE_CALL pop()
+ {
+ return static_cast<Type*>(m_impl.pop());
+ }
+};
+
+// -------------------------------------------------------------------------
+// $Log: $
+
+NS_BOOST_LOCKFREE_END
+
+#endif /* BOOST_LOCKFREE_STACK_HPP */

Modified: sandbox/memory/boost/memory/basic.hpp
==============================================================================
--- sandbox/memory/boost/memory/basic.hpp (original)
+++ sandbox/memory/boost/memory/basic.hpp 2008-05-06 09:48:59 EDT (Tue, 06 May 2008)
@@ -31,7 +31,7 @@
 #endif
 
 #ifndef BOOST_DETAIL_DEBUG_HPP
-#include "../detail/debug.hpp"
+#include <boost/detail/debug.hpp>
 #endif
 
 #pragma pack() // default pack

Modified: sandbox/memory/boost/memory/system_alloc.hpp
==============================================================================
--- sandbox/memory/boost/memory/system_alloc.hpp (original)
+++ sandbox/memory/boost/memory/system_alloc.hpp 2008-05-06 09:48:59 EDT (Tue, 06 May 2008)
@@ -17,7 +17,7 @@
 #endif
 
 #ifndef BOOST_DETAIL_THREADMODEL_HPP
-#include "../detail/threadmodel.hpp"
+#include <boost/detail/threadmodel.hpp>
 #endif
 
 #if !defined(_ALGORITHM_) && !defined(_ALGORITHM)

Modified: sandbox/memory/boost/memory/system_pool.hpp
==============================================================================
--- sandbox/memory/boost/memory/system_pool.hpp (original)
+++ sandbox/memory/boost/memory/system_pool.hpp 2008-05-06 09:48:59 EDT (Tue, 06 May 2008)
@@ -20,37 +20,94 @@
 #include "policy.hpp"
 #endif
 
+#ifndef BOOST_LOCKFREE_STACK_HPP
+#include <boost/lockfree/stack.hpp>
+#endif
+
 NS_BOOST_MEMORY_BEGIN
 
 // -------------------------------------------------------------------------
-// class system_pool_imp
+// class normal_stack
 
-template <class PolicyT>
-class system_pool_imp
+#if defined(BOOST_MEMORY_NO_LOCKFREE)
+
+class normal_stack
 {
 private:
- typedef typename PolicyT::threadmodel_type ThreadModel;
- typedef typename PolicyT::allocator_type AllocT;
- enum { cbBlock = PolicyT::MemBlockSize };
+ normal_stack(const normal_stack&);
+ void operator=(const normal_stack&);
+
+ typedef NS_BOOST_DETAIL::default_threadmodel::cs cs;
+ typedef cs::scoped_lock cslock;
 
- struct Block {
- Block* next;
+public:
+ class node
+ {
+ private:
+ node* m_prev;
+ friend class normal_stack;
+
+ public:
+ node() : m_prev(NULL) {}
+ node* prev() const { return m_prev; }
         };
- Block* m_freeList;
 
 private:
- typedef typename ThreadModel::cs cs;
- typedef typename ThreadModel::cslock cslock;
-
+ node* m_top;
         cs m_cs;
 
+public:
+ normal_stack() : m_top(NULL) {}
+
+ void BOOST_LOCKFREE_CALL push(node* val)
+ {
+ BOOST_DETAIL_ASSERT(val->m_prev == NULL);
+
+ cslock aLock(m_cs);
+ val->m_prev = m_top;
+ m_top = val;
+ }
+
+ node* BOOST_LOCKFREE_CALL clear()
+ {
+ cslock aLock(m_cs);
+ node* the_top = m_top;
+ m_top = NULL;
+ return the_top;
+ }
+
+ node* BOOST_LOCKFREE_CALL pop()
+ {
+ cslock aLock(m_cs);
+ node* the_top = m_top;
+ if (the_top == NULL)
+ return NULL;
+ m_top = m_top->m_prev;
+ return the_top;
+ }
+};
+
+#endif // defined(BOOST_MEMORY_NO_LOCKFREE)
+
+// -------------------------------------------------------------------------
+// class system_pool_imp
+
+template <class PolicyT, class StackT = NS_BOOST_LOCKFREE::stack>
+class system_pool_imp
+{
+private:
+ typedef typename PolicyT::allocator_type AllocT;
+ enum { cbBlock = PolicyT::MemBlockSize };
+
+ typedef typename StackT::node Block;
+ StackT m_freeList;
+
 private:
         system_pool_imp(const system_pool_imp&);
         void operator=(const system_pool_imp&);
 
 public:
         system_pool_imp()
- : m_freeList(NULL)
         {
         }
         ~system_pool_imp()
@@ -61,18 +118,15 @@
 public:
         void* BOOST_MEMORY_CALL allocate(size_t cb)
         {
- BOOST_MEMORY_ASSERT(m_cs.good());
                 BOOST_MEMORY_ASSERT(cb >= (size_t)cbBlock);
 
                 if (cb > (size_t)cbBlock)
                         return AllocT::allocate(cb);
                 {
- cslock aLock(m_cs);
- if (m_freeList)
+ Block* blk = m_freeList.pop();
+ if (blk)
                         {
- BOOST_MEMORY_ASSERT(AllocT::alloc_size(m_freeList) >= cb);
- Block* blk = m_freeList;
- m_freeList = blk->next;
+ BOOST_MEMORY_ASSERT(AllocT::alloc_size(blk) >= cb);
                                 return blk;
                         }
                 }
@@ -81,10 +135,7 @@
 
         void BOOST_MEMORY_CALL deallocate(void* p)
         {
- Block* blk = (Block*)p;
- cslock aLock(m_cs);
- blk->next = m_freeList;
- m_freeList = blk;
+ m_freeList.push((Block*)p);
         }
 
         static size_t BOOST_MEMORY_CALL alloc_size(void* p)
@@ -94,11 +145,11 @@
 
         void BOOST_MEMORY_CALL clear()
         {
- cslock aLock(m_cs);
- while (m_freeList)
+ Block* freeList = m_freeList.clear();
+ while (freeList)
                 {
- Block* blk = m_freeList;
- m_freeList = blk->next;
+ Block* blk = freeList;
+ freeList = freeList->prev();
                         AllocT::deallocate(blk);
                 }
         }
@@ -107,11 +158,12 @@
 // -------------------------------------------------------------------------
 // class system_pool_s
 
-template <class PolicyT>
+template <class PolicyT, class StackT = NS_BOOST_LOCKFREE::stack>
 class system_pool_s
 {
 private:
- typedef system_pool_imp<PolicyT> SystemPoolImpl;
+ typedef system_pool_imp<PolicyT, StackT> SystemPoolImpl;
+
         static SystemPoolImpl s_impl;
 
 public:
@@ -122,8 +174,8 @@
         }
 };
 
-template <class PolicyT>
-system_pool_imp<PolicyT> system_pool_s<PolicyT>::s_impl;
+template <class PolicyT, class StackT>
+system_pool_imp<PolicyT, StackT> system_pool_s<PolicyT, StackT>::s_impl;
 
 // -------------------------------------------------------------------------
 // class system_pool
@@ -138,7 +190,13 @@
 
 NS_BOOST_MEMORY_POLICY_END
 
+// -------------------------------------------------------------------------
+
+#if defined(BOOST_MEMORY_NO_LOCKFREE)
+typedef system_pool_s<NS_BOOST_MEMORY_POLICY::stdlib, normal_stack> system_pool;
+#else
 typedef system_pool_s<NS_BOOST_MEMORY_POLICY::stdlib> system_pool;
+#endif
 
 // -------------------------------------------------------------------------
 // $Log: $

Modified: sandbox/memory/boost/memory/thread/tls.hpp
==============================================================================
--- sandbox/memory/boost/memory/thread/tls.hpp (original)
+++ sandbox/memory/boost/memory/thread/tls.hpp 2008-05-06 09:48:59 EDT (Tue, 06 May 2008)
@@ -17,7 +17,7 @@
 #endif
 
 #ifndef BOOST_DETAIL_THREADMODEL_HPP
-#include "../../detail/threadmodel.hpp"
+#include <boost/detail/threadmodel.hpp>
 #endif
 
 // -------------------------------------------------------------------------

Modified: sandbox/memory/libs/memory/bin/win32/boost-memory.dll
==============================================================================
Binary files. No diff available.

Modified: sandbox/memory/libs/memory/memory.def
==============================================================================
--- sandbox/memory/libs/memory/memory.def (original)
+++ sandbox/memory/libs/memory/memory.def 2008-05-06 09:48:59 EDT (Tue, 06 May 2008)
@@ -1,2 +1,5 @@
 EXPORTS
         _boost_TlsBlockPool
+ _boost_SystemPoolAlloc
+ _boost_SystemPoolFree
+ _boost_SystemPoolSize

Modified: sandbox/memory/libs/memory/memory.dsp
==============================================================================
--- sandbox/memory/libs/memory/memory.dsp (original)
+++ sandbox/memory/libs/memory/memory.dsp 2008-05-06 09:48:59 EDT (Tue, 06 May 2008)
@@ -19,6 +19,7 @@
 !MESSAGE
 !MESSAGE "memory - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
 !MESSAGE "memory - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "memory - Win32 ReleaseCS" (based on "Win32 (x86) Dynamic-Link Library")
 !MESSAGE
 
 # Begin Project
@@ -81,12 +82,40 @@
 # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept
 # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /out:"bin/win32d/boost-memory.dll" /pdbtype:sept
 
+!ELSEIF "$(CFG)" == "memory - Win32 ReleaseCS"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "memory___Win32_ReleaseCS"
+# PROP BASE Intermediate_Dir "memory___Win32_ReleaseCS"
+# PROP BASE Ignore_Export_Lib 0
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "ReleaseCS"
+# PROP Intermediate_Dir "ReleaseCS"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MD /W3 /GX /O2 /I "../../" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "STDEXT_EXPORTS" /Yu"stdafx.h" /FD /c
+# ADD CPP /nologo /MD /W3 /GX /O2 /I "../../" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "STDEXT_EXPORTS" /D "BOOST_MEMORY_NO_LOCKFREE" /Yu"stdafx.h" /FD /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 /out:"bin/win32/boost-memory.dll"
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 /out:"bin/win32/boost-memory-cs.dll"
+
 !ENDIF
 
 # Begin Target
 
 # Name "memory - Win32 Release"
 # Name "memory - Win32 Debug"
+# Name "memory - Win32 ReleaseCS"
 # Begin Group "memory"
 
 # PROP Default_Filter ""

Modified: sandbox/memory/libs/memory/src/system_pool.cpp
==============================================================================
--- sandbox/memory/libs/memory/src/system_pool.cpp (original)
+++ sandbox/memory/libs/memory/src/system_pool.cpp 2008-05-06 09:48:59 EDT (Tue, 06 May 2008)
@@ -13,7 +13,7 @@
 
 // -------------------------------------------------------------------------
 
-#if defined(_WIN32)
+#if 1 // defined(_WIN32)
 
 #include <boost/memory/system_pool.hpp>
 

Modified: sandbox/memory/libs/memory/test/test_basic/memory/performance.cpp
==============================================================================
--- sandbox/memory/libs/memory/test/test_basic/memory/performance.cpp (original)
+++ sandbox/memory/libs/memory/test/test_basic/memory/performance.cpp 2008-05-06 09:48:59 EDT (Tue, 06 May 2008)
@@ -14,9 +14,10 @@
 
 #if defined(__GNUG__)
 #include <ext/mt_allocator.h>
+#endif
+
 #include <boost/pool/pool.hpp>
 #include <boost/pool/object_pool.hpp>
-#endif
 
 // -------------------------------------------------------------------------
 
@@ -78,6 +79,7 @@
                 m_acc.accumulate(counter.trace(log));
                 delete[] p;
         }
+#endif
 
         void doBoostPool(LogT& log, int NAlloc, int PerAlloc)
         {
@@ -110,7 +112,6 @@
                 }
                 m_acc.accumulate(counter.trace(log));
         }
-#endif
 
         template <class LogT2>
         void doAutoAlloc(LogT2& log, int NAlloc, int PerAlloc)
@@ -193,6 +194,7 @@
                 for (i = 0; i < Count; ++i)
                         doMtAllocator(log, NAlloc, PerAlloc);
                 m_acc.trace_avg(log);
+#endif
 
                 m_acc.start();
                 log.trace("\n===== BoostPool(%d) =====\n", PerAlloc);
@@ -205,7 +207,6 @@
                 for (i = 0; i < Count; ++i)
                         doBoostObjectPool(log, NAlloc, PerAlloc);
                 m_acc.trace_avg(log);
-#endif
 
                 m_acc.start();
                 log.trace("\n===== NewDelete(%d) =====\n", PerAlloc);

Modified: sandbox/memory/libs/memory/test/test_basic/test.dsp
==============================================================================
--- sandbox/memory/libs/memory/test/test_basic/test.dsp (original)
+++ sandbox/memory/libs/memory/test/test_basic/test.dsp 2008-05-06 09:48:59 EDT (Tue, 06 May 2008)
@@ -42,7 +42,7 @@
 # PROP Ignore_Export_Lib 0
 # PROP Target_Dir ""
 # ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /c
-# ADD CPP /nologo /MD /W3 /GX /Zi /O2 /I "../../../../" /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /FD /c
+# ADD CPP /nologo /MD /W3 /GX /Zi /O2 /I "../../../../" /I "../../../../../boost/" /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /FD /c
 # SUBTRACT CPP /YX /Yc /Yu
 # ADD BASE RSC /l 0x804 /d "NDEBUG"
 # ADD RSC /l 0x804 /d "NDEBUG"
@@ -67,7 +67,7 @@
 # PROP Ignore_Export_Lib 0
 # PROP Target_Dir ""
 # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /GZ /c
-# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "../../../../" /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /FD /GZ /c
+# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "../../../../" /I "../../../../../boost/" /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /FD /GZ /c
 # SUBTRACT CPP /YX /Yc /Yu
 # ADD BASE RSC /l 0x804 /d "_DEBUG"
 # ADD RSC /l 0x804 /d "_DEBUG"


Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk