Dynamic C++ Silicon Valley Code Camp 2012
Upcoming SlideShare
Loading in...5
×
 

Dynamic C++ Silicon Valley Code Camp 2012

on

  • 2,418 views

Silicon Valley Code Camp 2012 Presentation, with bias toward dynamic POCO Data access solution.

Silicon Valley Code Camp 2012 Presentation, with bias toward dynamic POCO Data access solution.

Statistics

Views

Total Views
2,418
Views on SlideShare
2,418
Embed Views
0

Actions

Likes
1
Downloads
8
Comments
0

0 Embeds 0

No embeds

Accessibility

Categories

Upload Details

Uploaded via as Adobe PDF

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

Dynamic C++ Silicon Valley Code Camp 2012 Dynamic C++ Silicon Valley Code Camp 2012 Presentation Transcript

  • Dynamic C++POCOC++ PORTABLE COMPONENTSalex@pocoproject.orgSunday, October 7, 12
  • Content> The Problem> The Solution> The Anatomy of the Solution> The Heart and Soul of the Solution> Let’s Dance - code example> Other solutions> Performance and comparisons> ConclusionSunday, October 7, 12
  • "Without a good library,mostinteresting tasks are hard to do in C++;but given a good library,almost anytask can be made easy."Bjarne Stroustrup(designer and original implementor of C++)Sunday, October 7, 12
  • A Brief History of Data AccessSunday, October 7, 12
  • Data Formats> often in proprietary binary format> transform into character strings of desired format> server-side needs an equivalent of HTML rendering engineSunday, October 7, 12
  • So,how do we do this?> generate the desired format in the database :-> use dynamic language> mix HTML with server-side code and compile on the fly (shudder)> browser plugin (double-shudder)> or ... use static language on the server-side and AJA(X|J) in the browser?Sunday, October 7, 12
  • SELECT * FROM Simpsons> discover column countThe Problem> discover column data types> bind returned data to variablesSunday, October 7, 12
  • SQLRETURN rc;SQLHENV henv = SQL_NULL_HENV;SQLHDBC hdbc = SQL_NULL_HDBC;SQLHSTMT hstmt = SQL_NULL_HSTMT;rc = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &henv);odbc_check_env (rc, henv);rc = SQLSetEnvAttr(henv, SQL_ATTR_ODBC_VERSION, (SQLPOINTER) SQL_OV_ODBC3, 0);odbc_check_env (rc, henv);rc = SQLAllocHandle(SQL_HANDLE_DBC, henv, &hdbc);odbc_check_dbc (rc, hdbc);SQLCHAR connectOutput[1024] = {0};SQLSMALLINT result;rc = SQLDriverConnect(hdbc,NULL,(SQLCHAR*)dbConnString.c_str(),(SQLSMALLINT)SQL_NTS,connectOutput,sizeof(connectOutput),&result,SQL_DRIVER_NOPROMPT);odbc_check_dbc (rc, hdbc);sql = "SELECT * FROM Simpsons";SQLCHAR* pStr = (SQLCHAR*) sql.c_str();rc = SQLPrepare(hstmt, pStr, (SQLINTEGER) sql.length());odbc_check_stmt (rc, hstmt);char name[50] = { 0 };SQLLEN lengths[3] = { 0 };int age = 0;float weight = 0.0f;std::memset(&sixth, 0, sizeof(sixth));rc = SQLBindCol(hstmt, (SQLUSMALLINT) 1, SQL_C_CHAR, (SQLPOINTER) chr, (SQLINTEGER) sizeof(chr[0]), &lengths[0]);odbc_check_stmt (rc, hstmt);rc = SQLBindCol(hstmt, (SQLUSMALLINT) 2, SQL_C_INTEGER, (SQLPOINTER) &age, (SQLINTEGER) sizeof(age), &lengths[1]);odbc_check_stmt (rc, hstmt);rc = SQLBindCol(hstmt, (SQLUSMALLINT) 3, SQL_C_BINARY, (SQLPOINTER) &weight, (SQLINTEGER) sizeof(weight), &lengths[2]);odbc_check_stmt (rc, hstmt);printf(“Name: %s, Age: %d, Weight: %f”, name, age, weight);! !“solution”© mark du toitSunday, October 7, 12
  • using namespace Poco::Data::SQLite;int main(){Session session("SQLite", "simpsons.db");std::cout << RecordSet(session,"SELECT * FROM Simpsons");return 0;}The Solution© mark du toitSunday, October 7, 12
  • Statement stmt =(session << "SELECT * FROM Simpsons", now);RecordSet rs(stmt);ostream& operator << (ostream &os,const RecordSet& rs){return rs.copy(os);}The Anatomy of the Solution(step - by - step)Sunday, October 7, 12
  • The Anatomy of the Solution(under the hood)using namespace std;ostream& RecordSet::copy(ostream& os, size_t offset = 0, size_t length = END){RowFormatter& rf = (*_pBegin)->getFormatter();os << rf.prefix();copyNames(os);copyValues(os, offset, length);os << rf.postfix();return os;}ostream& RecordSet::copyValues(ostream& os, size_t offset, size_t length){RowIterator begin = *_pBegin + offset;RowIterator end = (RowIterator::END != length) ? it + length : *_pEnd;std::copy(begin, end, std::ostream_iterator<Row>(os));return os;}Sunday, October 7, 12
  • Row& RowIterator::operator * (){if (END == _position)throw InvalidAccessException("End of iterator reached.");return _pRecordSet->row(_position);}ostream& operator << (ostream &os, const Row& row){os << row.valuesToString();return os;}const string& Row::valuesToString() const{return _pFormatter->formatValues(values(), _valueStr);}The Anatomy of the Solution,contd.(STL - compliance)Sunday, October 7, 12
  • class Row{public:// ...template <typename T>void set(size_t pos, const T& val){try { _values.at(pos) = val; }catch (out_of_range&){ throw RangeException("Invalid column."); }}// ...private:vector<Poco::Dynamic::Var> _values;};The Heart of the Solution(Row::set)Sunday, October 7, 12
  • namespace Poco {namespace Dynamic {class Var{public:// ...template <typename T>Var(const T& val):_pHolder(new VarHolderImpl<T>(val)){}// ...private:VarHolder* _pHolder;};} }The Soul of the Machine(Poco::Dynamic::Var)* Design based on boost::anySunday, October 7, 12
  • So,where was boost::any found lacking ?It’s a great idea with limited applicability -dynamic on receiving,but static on the giving end.using boost::any;using boost::any_cast;typedef std::list<any> many;int ival = 42;std::string sval = “fourty two”;values.push_back(ival);values.push_back(sval);std::string sival = values[0]; // oops!, compile errorsival = any_cast<std::string>(values[0]); // still oops!, throwSunday, October 7, 12
  • Var in Practical Usestd::string s1("string");Poco::Int8 s2(23);std::vector<Var> s16;s16.push_back(s1);s16.push_back(s2);Var a1(s16);std::string res = a1.convert<std::string>();// ["string", 23]DynamicStruct aStruct;aStruct["First Name"] = "Junior";aStruct["Last Name"] = "POCO";aStruct["Age"] = 1;Var a1(aStruct);std::string res = a1.convert<std::string>();// { "Age”: 1, "First Name": "Junior", "Last Name" : "POCO" }std::string str("42");Var v1 = str; // "42"double d = v1; // 42.0Var v2 = d + 1.0; // 43.0float f = v2 + 1; // 44.0Sunday, October 7, 12
  • What Else is in the Var Box> Dynamic array, pair and struct (map) support(Poco::Dynamic::Pair/Struct)> JSON (de)serialization of the above> Empty value support (very handy with null DB fields)> Strict conversion checksSunday, October 7, 12
  • namespace Poco {namespace Dynamic {class VarHolder{public:virtual ~VarHolder();virtual void convert(int& val) const;// ...protected:VarHolder();// ...};template <typename T> // for end-user extensionsclass VarHolderImpl: public VarHolder{//...};template <> // native and frequently used types specializations provided by POCOclass VarHolderImpl<int>: public VarHolder{//...};//...}}The Soul of the Machine(Poco::Dynamic::VarHolder)Sunday, October 7, 12
  • Poco::Net::HTTPServerThe Machine AssembledRecordSetStatementRowFormatterSessionPoco::Dynamic::VarSunday, October 7, 12
  • Let’s Danceclass DataRequestHandler: public HTTPRequestHandler{public:void handleRequest(HTTPServerRequest& request,HTTPServerResponse& response){response.setChunkedTransferEncoding(true);response.setContentType("text/xml");ostream& ostr = response.send();Session sess("SQLite", "sample.db");ostr << RecordSet(sess,"SELECT * FROM Simpsons",new XMLFormatter);}};Sunday, October 7, 12
  • A Real World ExampleSunday, October 7, 12
  • Is it REALLY Dynamic?Of course not.Dig deep enough and there is no such thing asdynamic.Type handlers are templates,hence generatedby compiler and statically checked for type.Sunday, October 7, 12
  • And there’s a price to pay ...Binary sizes:============Linux-----5160 AnySize.o23668 DynamicAnySizeExtract.o25152 DynamicAnySizeConvert.o9600 lexical_cast_size.oWindows-------26,924 AnySize.obj96,028 DynamicAnySizeExtract.obj103,943 DynamicAnySizeConvert.obj84,217 lexical_cast_size.objLines of code:=============Any 145DynamicAny* 3,588lexical_cast 971Sunday, October 7, 12
  • struct Person{std::string name;std::string address;int age;};But what if I need performance?There is,of course,a lean and elegant static workaround.In fact,several of them ...Sunday, October 7, 12
  • namespace Poco {namespace Data {template <>class TypeHandler<Person>{public:static std::size_t size(){return 3;}static void bind(size_t pos, const Person& person, AbstractBinder* pBinder, Direction dir){TypeHandler<std::string>::bind(pos++, person.name, pBinder, dir);TypeHandler<std::string>::bind(pos++, person.address, pBinder, dir);TypeHandler<int>::bind(pos++, person.age, pBinder, dir);}static void extract(size_t pos, Person& person, const Person& deflt, AbstractExtractor* pE){TypeHandler<std::string>::extract(pos++, person.name, deflt.name, pExtr);TypeHandler<std::string>::extract(pos++, person.address, deflt.address, pExtr);TypeHandler<int>::extract(pos++, person.age, deflt.age, pExtr);}};} }Scaffolding - wrap Person into a TypeHandlerSunday, October 7, 12
  • Person person ={"Bart Simpson","Springfield",12};session << "INSERT INTO Person VALUES(?, ?, ?)", use(person);std::vector<Person> people;session << "SELECT Name, Address, Age FROM Person",into(people), now;And Life is Good Againstd::string name, address;int age;session << "INSERT INTO Person VALUES(?, ?, ?)",use(name),use(address),use(age);Sunday, October 7, 12
  • using namespace std;using namespace Poco;typedef Tuple<string, string, int> Person;typedef vector<Person> People;People people;people.push_back(Person("Bart Simpson", "Springfield", 12));people.push_back(Person("Lisa Simpson", "Springfield", 10));session << "INSERT INTO Person VALUES(?, ?, ?)", use(people), now;people.clear();session << "SELECT Name, Address, Age FROM Person", into(people), now;But wait,there’s more!Sunday, October 7, 12
  • What else is out there ?> void*> C union> MS COM Variant> boost::variant> boost::lexical_cast> boost::type_erasure> folly::dynamicSunday, October 7, 12
  • Linux Performance WindowsSunday, October 7, 12
  • ACCU Overload Journal Articleshttp://accu.org/index.php/journals/1511http://accu.org/index.php/journals/1502Sunday, October 7, 12
  • Last but not LeastPOCO> large, comprehensive, well-designed framework> designed for practical everyday use, with end-user in mind> makes C++ programming fun> 100% standard C++> not reinventing the wheel (except when necessary ;-)http://poco.svn.sourceforge.net/viewvc/poco/poco/trunkhttps://poco.svn.sourceforge.net/svnroot/poco/poco/trunkhttp://pocoproject.orgSunday, October 7, 12
  • got POCO?C++ PORTABLE COMPONENTShttp://pocoproject.org alex@pocoproject.orgSunday, October 7, 12