Re: [Harbour] 2007-11-30 20:25 UTC+0100 Marek Paliwoda (mpaliwoda at interia pl)
Hi Marek, Przemek and all, Just a small comment on the threading topic, maybe it'd be worth to mark thread static vars with a "ts_" prefix to clearly differentiate them from app wide statics. Very very nice addition to Harbour. Brgds, Viktor On 2008.01.10., at 14:15, Przemyslaw Czerpak wrote: On Wed, 09 Jan 2008, Mindaugas Kavaliauskas wrote: * harbour/source/rtl/perfuncs.prg * harbour/source/rtl/menuto.prg * harbour/source/rtl/getlist.prg * harbour/source/rtl/readvar.prg * harbour/source/rtl/text.prg * use STATIC THREAD variables to make above code MT safe Pritpal Bedi wrote: Interesting. And most-interesting part is getlist.prg and readvar.prg. Even Xbase++ does not have this feature. hmmm... How do you see changes in getlist.prg and readvar.prg? This is changelog of proposed commit only. I can't find it on SVN or attached to the email. The modifications are minimal. I did not have to change anything in the code and only added THREAD keyword to static variable declarations. Rest is done inside HVM. I'm attaching patch for current SVN with above modifications if you are interested. This is very important extension for me because it easy allows to create MT safe code which can be used also in ST applications without introducing additional synchronization mechanisms. In Harbour all core libraries except HVM will be common for MT and ST mode. After 1.0 I plan to implement MT version of HVM in spare time. I plan to add full SETs, MEMVARs and WAs separation in the basic version. Later I'll add optional sharing on user requests. SET callback functions will also have to be thread local to avoid problems which can appear in some 3-rd party code, f.e. ADSRDD which cannot follow our thread local data. In fact this RDD cannot be fully thread separated do to limitation in ACE library but native ones will be. Best regards, Przemek ___ Harbour mailing list Harbour@harbour-project.org http://lists.harbour-project.org/mailman/listinfo/harbour ___ Harbour mailing list Harbour@harbour-project.org http://lists.harbour-project.org/mailman/listinfo/harbour
Re: [Harbour] How to gzip a string?
On Thu, 10 Jan 2008, Szakáts Viktor wrote: > Hi Mindaugas, > Since I believe you will commit these wrappers > to the contrib area (since these might have > 3rd party lib dependencies, unless we include > these sources in core), I think it's fine to release > them anytime, even now. I also agree. If it's new contrib project then please commit it. I also think that we should remove HB_I18N_SUPPORT macro and enable code covered by this macro in default builds. It's quite well tested, does not break other code and open door for adding i18n tools to Harbour which will be separated from existing code so will not break anything. I'll add item functions Mindaugas asked ASAP. Victor, do you plan to update TBROWSE class before release? If not then I think it's time to start release process. best regards, Przemek ___ Harbour mailing list Harbour@harbour-project.org http://lists.harbour-project.org/mailman/listinfo/harbour
Re: [Harbour] How to gzip a string?
Hi Przemek, On 2008.01.11., at 12:59, Przemyslaw Czerpak wrote: On Thu, 10 Jan 2008, Szakáts Viktor wrote: Hi Mindaugas, Since I believe you will commit these wrappers to the contrib area (since these might have 3rd party lib dependencies, unless we include these sources in core), I think it's fine to release them anytime, even now. I also agree. If it's new contrib project then please commit it. I also think that we should remove HB_I18N_SUPPORT macro and enable code covered by this macro in default builds. It's quite well tested, does not break other code and open door for adding i18n tools to Harbour which will be separated from existing code so will not break anything. I agree. I'll add item functions Mindaugas asked ASAP. Victor, do you plan to update TBROWSE class before release? If not then I think it's time to start release process. Let's start the release, I couldn't yet find enough continuous time to take a deep jump into TBROWSE. Brgds, Viktor ___ Harbour mailing list Harbour@harbour-project.org http://lists.harbour-project.org/mailman/listinfo/harbour
[Harbour] ChangeLog 2008-01-11 17:32 UTC+0200 Mindaugas Kavaliauskas
2008-01-11 17:32 UTC+0200 Mindaugas Kavaliauskas (dbtopas/at/dbtopas.lt) * harbour/include/hbexprb.c * harbour/source/compiler/hbmain.c ! added string escaping before to i18n .pot files + added hb_i18n_gettext_strict() support for compiler. This function generates warning if argument is not literal string. See discussion on mailing list from 2007-11-23 to 2007-11-29, for details. I also think that we should remove HB_I18N_SUPPORT macro and enable code covered by this macro in default builds. It's quite well tested, does not break other code and open door for adding i18n tools to Harbour which will be separated from existing code so will not break anything. Hi, one thing was missing - strings were not escaped before writing to .pot file. This is important fix, if we want to include i18n in current release. So, I've committed the change. I've implemented this a month ago and used code until now, so I hope there are no nasty bugs in new code. Best regards, Mindaugas ___ Harbour mailing list Harbour@harbour-project.org http://lists.harbour-project.org/mailman/listinfo/harbour
[Harbour] 2008-01-11 18:01 UTC+0100 Przemyslaw Czerpak (druzus/at/priv.onet.pl)
2008-01-11 18:01 UTC+0100 Przemyslaw Czerpak (druzus/at/priv.onet.pl) * harbour/include/hbapiitm.h * harbour/source/vm/itemapi.c + added new functions: BOOL hb_itemParamStore( USHORT uiParam, PHB_ITEM pItem ) BOOL hb_itemParamStoreForward( USHORT uiParam, PHB_ITEM pItem ) They copy/move pItem body to parameter passed by reference and return TRUE when operation was done successfully (uiParam was passed by reference) + added new functions for string manipulation: char * hb_itemLockReadCPtr( PHB_ITEM pItem, ULONG * pulLen ); char * hb_itemLockWriteCPtr( PHB_ITEM pItem, ULONG * pulLen ); void hb_itemUnLockCPtr( char * pszString ); It's recommended to use them instead of hb_itemGetCPtr(). Pointer to string buffer returned by hb_itemLockReadCPtr() will be always valid even if source item will be cleared, destroyed or overwritten until hb_itemUnLockCPtr() is called. Each locked string has to be unlocked to avoid memory leaks. After unlocking the string pointer cannot be longer used. hb_itemLockWriteCPtr() works like hb_itemLockReadCPtr() but string pointer returned by this function is writable so user can change the body of string item. It's the _ONLY_ one way when it's possible. Modifying string items using pointers returned by hb_parc() or hb_itemGetCPtr() or extracted directly from HB_ITEM body is _FORBIDDEN_ and can cause unpredictable results (GPF when constant/readonly memory pages are changed, changing many different items which share the same memory buffer, etc.). This is code illustrates how to use hb_itemLockReadCPtr()/ hb_itemUnLockCPtr() and it's also good example why hb_itemGetCPtr() is very danger function and cannot be used in such case - if you replace hb_itemLockReadCPtr() with hb_itemGetCPtr() and remove hb_itemUnLockCPtr() then you will have buggy code. HB_FUNC( MYFUNC ) { PHB_ITEM pObject = hb_param( 1, HB_IT_OBJECT ) if( pObject ) { char * pszName1, * pszName2; PHB_ITEM pResult; pResult = hb_objSendMsg( pObject, "POP", 0 ); pszName1 = hb_itemLockReadCPtr( pResult, NULL ); pResult = hb_objSendMsg( pObject, "POP", 0 ); pszName2 = hb_itemLockReadCPtr( pResult, NULL ); if( pszName1 && pszName2 ) hb_retc_buffer( hb_xstrcpy( NULL, "[", pszName1, "]-[", pszName2, "]", NULL ) ); hb_itemUnLockCPtr( pszName1 ); hb_itemUnLockCPtr( pszName2 ); } } This code shows how to use hb_itemLockWriteCPtr(): proc main() local cVal, cVal2 cVal := cVal2 := "ABC" STRPUT( @cVal2, 2, 42 ) ? cVal, cVal2 return #pragma begindump #include "hbapiitm.h" HB_FUNC( STRPUT ) { PHB_ITEM pString = hb_param( 1, HB_IT_STRING ); ULONG ulAt = hb_parnl( 2 ); if( pString && ulAt && ISNUM( 3 ) ) { ULONG ulLen; char * pszValue; pszValue = hb_itemLockWriteCPtr( pString, &ulLen ); if( pszValue ) { if( ulAt <= ulLen ) pszValue[ ulAt - 1 ] = ( char ) hb_parni( 3 ); hb_itemUnLockCPtr( pszValue ); } } } #pragma enddump * harbour/include/hbcompdf.h * harbour/include/hbexprop.h * harbour/include/hbexprb.c * harbour/source/compiler/hbmain.c * harbour/source/compiler/cmdcheck.c * harbour/source/compiler/hbusage.c * removed HB_I18N_SUPPORT macro and enabled I18N code in default build best regards Przemek ___ Harbour mailing list Harbour@harbour-project.org http://lists.harbour-project.org/mailman/listinfo/harbour
[Harbour] 2008-01-11 18:13 UTC+0100 Przemyslaw Czerpak (druzus/at/priv.onet.pl)
2008-01-11 18:13 UTC+0100 Przemyslaw Czerpak (druzus/at/priv.onet.pl) * harbour/include/hbexprb.c * removed unused variable best regards Przemek ___ Harbour mailing list Harbour@harbour-project.org http://lists.harbour-project.org/mailman/listinfo/harbour
Re: [Harbour] ChangeLog 2008-01-11 17:32 UTC+0200 Mindaugas Kavaliauskas
On Fri, 11 Jan 2008, Mindaugas Kavaliauskas wrote: > one thing was missing - strings were not escaped before writing to .pot > file. This is important fix, if we want to include i18n in current > release. So, I've committed the change. Thank you. I'll remove HB_I18N_SUPPORT in a while. best regards, Przemek ___ Harbour mailing list Harbour@harbour-project.org http://lists.harbour-project.org/mailman/listinfo/harbour
Re: [Harbour] 2008-01-11 18:01 UTC+0100 Przemyslaw Czerpak (druzus/at/priv.onet.pl)
Hi Przemek, I think there is such an unsafe usage of hb_itemGetCPtr() in philes.c / FREAD(). That one sprang to my mind, but maybe there are more. Brgds, Viktor On 2008.01.11., at 18:01, Przemyslaw Czerpak wrote: 2008-01-11 18:01 UTC+0100 Przemyslaw Czerpak (druzus/at/priv.onet.pl) * harbour/include/hbapiitm.h * harbour/source/vm/itemapi.c + added new functions: BOOL hb_itemParamStore( USHORT uiParam, PHB_ITEM pItem ) BOOL hb_itemParamStoreForward( USHORT uiParam, PHB_ITEM pItem ) They copy/move pItem body to parameter passed by reference and return TRUE when operation was done successfully (uiParam was passed by reference) + added new functions for string manipulation: char * hb_itemLockReadCPtr( PHB_ITEM pItem, ULONG * pulLen ); char * hb_itemLockWriteCPtr( PHB_ITEM pItem, ULONG * pulLen ); void hb_itemUnLockCPtr( char * pszString ); It's recommended to use them instead of hb_itemGetCPtr(). Pointer to string buffer returned by hb_itemLockReadCPtr() will be always valid even if source item will be cleared, destroyed or overwritten until hb_itemUnLockCPtr() is called. Each locked string has to be unlocked to avoid memory leaks. After unlocking the string pointer cannot be longer used. hb_itemLockWriteCPtr() works like hb_itemLockReadCPtr() but string pointer returned by this function is writable so user can change the body of string item. It's the _ONLY_ one way when it's possible. Modifying string items using pointers returned by hb_parc() or hb_itemGetCPtr() or extracted directly from HB_ITEM body is _FORBIDDEN_ and can cause unpredictable results (GPF when constant/readonly memory pages are changed, changing many different items which share the same memory buffer, etc.). This is code illustrates how to use hb_itemLockReadCPtr()/ hb_itemUnLockCPtr() and it's also good example why hb_itemGetCPtr() is very danger function and cannot be used in such case - if you replace hb_itemLockReadCPtr() with hb_itemGetCPtr() and remove hb_itemUnLockCPtr() then you will have buggy code. HB_FUNC( MYFUNC ) { PHB_ITEM pObject = hb_param( 1, HB_IT_OBJECT ) if( pObject ) { char * pszName1, * pszName2; PHB_ITEM pResult; pResult = hb_objSendMsg( pObject, "POP", 0 ); pszName1 = hb_itemLockReadCPtr( pResult, NULL ); pResult = hb_objSendMsg( pObject, "POP", 0 ); pszName2 = hb_itemLockReadCPtr( pResult, NULL ); if( pszName1 && pszName2 ) hb_retc_buffer( hb_xstrcpy( NULL, "[", pszName1, "]-[", pszName2, "]", NULL ) ); hb_itemUnLockCPtr( pszName1 ); hb_itemUnLockCPtr( pszName2 ); } } This code shows how to use hb_itemLockWriteCPtr(): proc main() local cVal, cVal2 cVal := cVal2 := "ABC" STRPUT( @cVal2, 2, 42 ) ? cVal, cVal2 return #pragma begindump #include "hbapiitm.h" HB_FUNC( STRPUT ) { PHB_ITEM pString = hb_param( 1, HB_IT_STRING ); ULONG ulAt = hb_parnl( 2 ); if( pString && ulAt && ISNUM( 3 ) ) { ULONG ulLen; char * pszValue; pszValue = hb_itemLockWriteCPtr( pString, &ulLen ); if( pszValue ) { if( ulAt <= ulLen ) pszValue[ ulAt - 1 ] = ( char ) hb_parni( 3 ); hb_itemUnLockCPtr( pszValue ); } } } #pragma enddump * harbour/include/hbcompdf.h * harbour/include/hbexprop.h * harbour/include/hbexprb.c * harbour/source/compiler/hbmain.c * harbour/source/compiler/cmdcheck.c * harbour/source/compiler/hbusage.c * removed HB_I18N_SUPPORT macro and enabled I18N code in default build best regards Przemek ___ Harbour mailing list Harbour@harbour-project.org http://lists.harbour-project.org/mailman/listinfo/harbour ___ Harbour mailing list Harbour@harbour-project.org http://lists.harbour-project.org/mailman/listinfo/harbour
[Harbour] 2008-01-11 22:35 UTC+0100 Przemyslaw Czerpak (druzus/at/priv.onet.pl)
2008-01-11 22:35 UTC+0100 Przemyslaw Czerpak (druzus/at/priv.onet.pl) * harbour/source/vm/itemapi.c ! use hb_xRefFree() instead of hb_xRefDec() in hb_itemUnLockCPtr() It's necessary when source item is cleared before. best regards Przemek ___ Harbour mailing list Harbour@harbour-project.org http://lists.harbour-project.org/mailman/listinfo/harbour
Re: [Harbour] 2008-01-11 18:01 UTC+0100 Przemyslaw Czerpak (druzus/at/priv.onet.pl)
On Fri, 11 Jan 2008, Szakáts Viktor wrote: > Hi Przemek, > I think there is such an unsafe usage of hb_itemGetCPtr() > in philes.c / FREAD(). > That one sprang to my mind, but maybe there are more. Now it's safe because hb_itemUnShareString() is used but I would like to eliminae this functions from public API and replace it with hb_itemLockWriteCPtr()/hb_itemUnLockCPtr() so I'll update FREAD() and also HB_INETRECV(), HB_INETDGRAMRECV(), STRPOKE() and HB_UTF8POKE() ASAP. I also want to cover hb_parcsiz() usage in FREAD() by HB_C52_STRICT macro. I do not like that public .prg level function allows to eliminate chr(0) terminator from HB_ITEM strings what can be source of some unpredictable errors (f.e. GPF) in other subsystems which expects that strings are always NULL terminated. I hope it will not be very big problem. best regards, Przemek ___ Harbour mailing list Harbour@harbour-project.org http://lists.harbour-project.org/mailman/listinfo/harbour
Re: [Harbour] 2008-01-11 18:01 UTC+0100 Przemyslaw Czerpak (druzus/at/priv.onet.pl)
Przemyslaw Czerpak wrote: + added new functions for string manipulation: char * hb_itemLockReadCPtr( PHB_ITEM pItem, ULONG * pulLen ); char * hb_itemLockWriteCPtr( PHB_ITEM pItem, ULONG * pulLen ); void hb_itemUnLockCPtr( char * pszString ); It's recommended to use them instead of hb_itemGetCPtr(). Pointer to string buffer returned by hb_itemLockReadCPtr() will be always valid even if source item will be cleared, destroyed or overwritten until hb_itemUnLockCPtr() is called. Each locked string has to be unlocked to avoid memory leaks. After unlocking the string pointer cannot be longer used. hb_itemLockWriteCPtr() works like hb_itemLockReadCPtr() but string pointer returned by this function is writable so user can change the body of string item. It's the _ONLY_ one way when it's possible. Modifying string items using pointers returned by hb_parc() or hb_itemGetCPtr() or extracted directly from HB_ITEM body is _FORBIDDEN_ and can cause unpredictable results (GPF when constant/readonly memory pages are changed, changing many different items which share the same memory buffer, etc.). This is code illustrates how to use hb_itemLockReadCPtr()/ hb_itemUnLockCPtr() and it's also good example why hb_itemGetCPtr() is very danger function and cannot be used in such case - if you replace hb_itemLockReadCPtr() with hb_itemGetCPtr() and remove hb_itemUnLockCPtr() then you will have buggy code. HB_FUNC( MYFUNC ) { PHB_ITEM pObject = hb_param( 1, HB_IT_OBJECT ) if( pObject ) { char * pszName1, * pszName2; PHB_ITEM pResult; pResult = hb_objSendMsg( pObject, "POP", 0 ); pszName1 = hb_itemLockReadCPtr( pResult, NULL ); pResult = hb_objSendMsg( pObject, "POP", 0 ); pszName2 = hb_itemLockReadCPtr( pResult, NULL ); if( pszName1 && pszName2 ) hb_retc_buffer( hb_xstrcpy( NULL, "[", pszName1, "]-[", pszName2, "]", NULL ) ); hb_itemUnLockCPtr( pszName1 ); hb_itemUnLockCPtr( pszName2 ); } } Hi, what are situations and rules to use hb_itemLockReadCPtr()? Pointer to C string could be obtained not only by using hb_itemGetCPtr(). There is a number of other methods, hb_parc() is an example. HB_FUNC( MYFUNC2 ) { char* szParam = hb_parc( 1 ); hb_vmDynSym( hb_dynsymFind( "SOMEOTHERFUNC" ) ); hb_vmPushNil(); hb_vmPushLocalByRef( 1 ); hb_vmDo( 1 ); ... any operation on szParam is invalid ... } Well, a little bit artificial example, but it could be realistic if hb_vm*() is hidden under call of some other function. The problem of your example is that pResult is return item of hb_stack, and it could be reused to store other items if we call some function that operates on hb_stack, hb_objSendMsg() in this case. If pResult would be owned not by hb_stack, but owned by MYFUNC, we'll have no problem. Let's last line of hb_objSendMsg() be return hb_itemNew( hb_stackReturnItem() ); instead of return hb_stackReturnItem(); In this case MYFUNC owns pResult and is responsible to free it. MYFUNC code would be: pResult1 = hb_objSendMsg( pObject, "POP", 0 ); pszName1 = hb_itemGetCPtr( pResult1 ); pResult2 = hb_objSendMsg( pObject, "POP", 0 ); pszName2 = hb_itemGetCPtr( pResult2 ); if( pszName1 && pszName2 ) hb_retc_buffer( ... ); hb_itemRelease( pResult1 ); hb_itemRelease( pResult2 ); Locking idea is replaced by idea of owning, unlocking item is equivalent to freeing it. This code looks a little more clear for me. BTW, this approach to solve problem of reusing hb_stack's return item is used in hb_itemDo(). The problem of MYFUNC2 is a little more complicated, because here we use ExtendAPI and we change value of parameter, not a return value. ExtendAPI does not operate on items and item could not be owned by MYFUNC2, but a rule of thumb could be made: if function allows to change it's parameters on hb_stack (ex., by passing it by reference), it should make item's copy for itself: PHB_ITEM pItem = hb_itemNew( hb_param( 1, HB_IT_STRING ) ); char* szParam = hb_itemGetCPtr( pItem ); hb_vmDynSym( hb_dynsymFind( "SOMEOTHERFUNC" ) ); hb_vmPushNil(); hb_vmPushLocalByRef( 1 ); hb_vmDo( 1 ); ... some operation on szParam ... hb_itemRelease( pItem ); Of cause arrays could be a source of nasty bugs: char* szParam = hb_parc( 1, 1 ); since arrays are always a references. I feel my letter is more like brainstorming before a sleep than a letter of the ideas I really want to see implemented. Usage of hb_stackReturnItem() is more fast than making a copy of item. In many cases hb_stackReturnItem() is OK. Maybe we can use hb_stackReturnItem() for internal code