1 / 25

Statics in Depth

Statics in Depth. Advanced C++ Programming Anton Kaiser, Summer Term 2012. In other words . Please Avoid Statics. Advanced C++ Programming Anton Kaiser, Summer Term 2012. Outline. Overview Global Objects Statics Initialization Problems Ordering Multithreading

naasir
Download Presentation

Statics in Depth

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Statics in Depth Advanced C++ Programming Anton Kaiser, Summer Term 2012

  2. In otherwords... PleaseAvoidStatics Advanced C++ Programming Anton Kaiser, Summer Term 2012

  3. Outline • Overview • Global Objects • Statics • Initialization • Problems • Ordering • Multithreading • Possible Solutions • AvoidingStatics • Singleton • Schwarz Counter • Spinlocks • Conclusions • Sources

  4. Overview • Where do staticsreside? • Special part in thedatasegment • When do staticsexist? • Duringthewholelifetimeof a program • Whatiftheyhave not beeninitialized? • Staticprimitive variables areinitializedto NULL • Forobjects (likestrings) thestandardconstructor will becalled

  5. Overview • Global objects • Accessiblefromeveryfileandfunctionoftheprogram • Typicalexamples: cin, cout, cerr, clog • //Class1.cpp • stringline; // global • intmain() {…} • //Class2.cpp • externstringline; • intlineSize() { • returnline.size(); • }

  6. Overview • Staticobjects • Accessibleonlyfromfunctions in the same file, depending on thelocationtheyhavebeendefinedat • In thewholemodule, whendefined outside all functions • Locally in a blockwheredefined • //AccessControl.cpp • staticstringpassword = "coolPassword"; • booltestPasswordInput(string &pw) { • if (pw.compare (password) == 0) • returntrue; • elsereturnfalse; • } • //returnsthe time differencesincethe last call • longtimeDiff() { • statictime_tseconds = 0; //0 onlyassignedonce! • longoldSeconds = seconds; //save old time • time( &seconds); //getnew time • return (seconds - oldSeconds); //returndifference • }

  7. Overview • Initialization • First phase: staticinitialization (atcompile time) • Second phase: dynamicinitialization • externintsomeOtherModulesFunc(); • namespaceStaticsAbound { • inlineintlocalFunc() { return 10 }; • struct Thing { • Thing() : i(someOtherModulesFunc()) {} • int i; • } thing; // dynamic • int i1 = 0; int i2; int i3 = 1; // static • int i4 = localFunc(); // static • int i5 = ::SomeOtherModulesFunc(); // dynamic • }

  8. Outline • Overview • Global Objects • Statics • Initialization • Problems • Ordering • Multithreading • Possible Solutions • AvoidingStatics • Singleton • Schwarz Counter • Spinlocks • Conclusions • Sources

  9. Problems:IntracompilationOrdering extern someObjecto2; // declaration someObject o1(o2); // undefined! someObject o1("o1"); // definition someObjecto2(o1); // thisisfine! intmain() { someObject o3("o3"); return 0; } •  Objects areinitializedby order ofdefinition, not declaration!

  10. Problems:IntercompilationOrdering // object.h classObject {…}; externObject o1; externObject o2; externObject o3; // object2.cpp • #include"object.h" • Object o2("o2"); // object3.cpp • #include"object.h" • Object o3("o3"); Recommendation • Don’t rely on global object initialization ordering • Do utilize global object initialization tracing mechanisms anyway // objects01.cpp • #include"object.h" • Object o0("o0"); • Object o1("o1"); • intmain() {...}

  11. Problems: Multithreading (1) • Racecondition • Twothreadscouldbothseetheuninitializedresult int myFunction() { static int result = doCalculation(); return result; } int myFunction() { static bool finished = false; static int result; if (!finished) { finished = true; result = doCalculation(); } return result; } • Racecondition • Twothreadscouldreadfinishedsimultaniously,bothexecutedoCalculation()andwritetoresult

  12. Problems: Multithreading (2) • Initialization • myClassmay not havebeeninitializedbeforethecalculation class MyClass {...}; int myFunction{...}; static MyClass myClass; return myClass.doCalculation(); } class MyClass {...}; int calculateResult() { static bool isConstructed = false; static MyClass myClass; // uninitialized if (!isConstructed) { myClass.isConstructed = true; new (&myClass) myClass; atexit(destruct_myClass); return myClass.doCalculation(); } • Racecondition • myClasscouldbe double-constructedand double-destructed

  13. Problems: Multithreading (3) • Proposition • Locking out otherthreads int calculateResult() { Lock myLock(myMutex); // only one thread gets past here static int result = doCalculation(); return result; } • Problem • doCalculation()orany sub-functionofitcouldcallcalculateResult() •  Thethreadalreadyhasthe lock, thereforecan enter thesynchronized block andagainseeuninitializedresult!

  14. Outline • Overview • Global Objects • Statics • Initialization • Problems • Ordering • Multithreading • Possible Solutions • AvoidingStatics • Singleton • Schwarz Counter • Spinlocks • Conclusions • Sources

  15. Possible Solutions:AvoidingStatics • Avoidusingstaticswheneverpossible • Usereferencesasparametersinsteadof global variables // Usingstatics • static MyClass myClass; • void myFunction() { • myClass.doCalculation(); • } • int main() { • myFunction(); • } // Usingreferences • void myFunction(MyClass &myClass) { • myClass.calculate(); • } • int main() { • MyClass myClass; • myFunction(myClass); • return 0; • }

  16. Possible Solutions:AvoidingStatics • It‘spossibletousestack variables in main() • A littlebitof a hack • Lifetimeandorderingcontrol // SomeClass.h classSomeClass {…}; • extern SomeClass*g_ptr_someClass; // main.cpp • #include "SomeClass.h" • int main() { • SomeClasso1; • g_ptr_someClass = &o1; • returng_ptr_someClass->func(); • } • Downsides • Inconvenientsyntax (use global variables bypointers) • Loss in efficiency

  17. Possible Solutions: Singleton (1) • Meyer‘s Singleton • Controlovercreation time • Nocontroloverdestruction time (duringprocessshutdown) • IfsomedestructorcallsGetInstance() after thedestructionofs_instance, theprogram will beworkingwith an uninitializedobject, whichisknownas„Dead Reference problem“ • Using a staticlocalobjectis vulnerable toraceconditions in multithreadedenvironments

  18. Possible Solutions: Singleton (2) • Alexandrescu Singleton • Can be made thread-safe • Solves the Dead Reference problem by providing the GetLongevity methods for specification of destruction order • Downsides: • A lot of effort if new singletons are inserted into the system • The programmer provides the ranking values  “Easy to get it wrong” and errors are very hard to detect

  19. Possible Solutions: Schwarz Counter • Also knownas „Nifty Counter“ • Usedby Standard C++ iostreamlibrary • Ensuringstaticobjectstobeavailablebeforemainlineexecution, andbeforetheyareusedbyanyotherstaticobjects

  20. Possible Solutions: Schwarz Counter • // Stream.hpp • classStreamInitializer; • classStream { • friendclassStreamInitializer; • public: • Stream() { /* Constructor must becalledbeforeuse. */ } • }; • staticclassStreamInitializer { • public: • StreamInitializer(); • ~StreamInitializer(); • } initializer;

  21. Possible Solutions: Schwarz Counter • The header file of the Stream class has to be included before any member function can be called on the Stream object • This ensures that the constructor of the initializer object is called before the Stream object is used. • // Stream.cpp • staticintnifty_counter; // initializationofthecounter • StreamInitializer::StreamInitializer() { • if (0 == nifty_counter++) • // initializationofthestreamobject‘sstaticmembers • } • StreamInitializer::~StreamInitializer() { • if (0 == --nifty_counter) • // cleaningup • }

  22. Possible Solutions:Spinlocksfor Multithreading • The spinlockitselfiscostly • In mostcasesfunction-localstaticobjectsare not beingaccessedtoooftenbytoomanythreads • The guardedsectionisveryshort • MyClass &getInstance(); // initializationofthecounter • { • staticintguard; // initializedtozero • spin_mutex(&guard); • lock_scope<spin_mutex> lock(smx); • staticMyClassinstance; • returninstance; • }

  23. Outline • Overview • Global Objects • Statics • Initialization • Problems • Ordering • Multithreading • Possible Solutions • AvoidingStatics • Singleton • Schwarz Counter • Spinlocks • Conclusions • Sources

  24. Conclusions • Staticobjectscan bring alongseriousproblems • Avoidthemwheneveryoucan! • Ifreallyneeded, alwaysbesureabout • Scopeandlifetime • Construction Order • Multithreading issues • Possiblesolutionscanbe • Singletons, Schwarz Counter • Lockingwithspinlocks

  25. Sources • M. Wilson, Imperfect C++: Practical Solutions for Real-Life Programming, Addison-Wesley, 2004 • M. Götze, Presentation in the Seminar on Advanced C++ Programming, FAU Erlangen-Nürnberg, 2011 • G. Loganathan, Presentation in the Seminar on Advanced C++ Programming, FAU Erlangen-Nürnberg, 2012 • Prinz, Peter, C++ Lernen und professionell anwenden, MITP-Verlag, 1999 • U. Breymann, C++ Eine Einführung, 5th edition, Hanser Verlag, 1999 • S. Prata, C++: Eine Einführung in die objektorientierte Programmierung, 8th edition, te-wi Verlag, 1992 • Schwarz Counter C++ Idiom https://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Nifty_Counter

More Related