Changeset 20392
- Timestamp:
- 06/29/07 16:33:10 (1 year ago)
- Files:
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
juggler/branches/2.2/modules/gadgeteer/doc/device.driver.guide/device.driver.guide.xml
r19729 r20392 916 916 cannot be shared between computers.</para> 917 917 918 <note> 919 <para>As of this writing, the Input Mixer is not expected to be 920 a long-term solution. A future version of Gadgeteer may do away 921 with <classname>gadget::InputMixer<S,T></classname>, and 922 as such, driver authors should be aware of potential API 923 changes in the future.</para> 924 </note> 918 <para>When deriving from 919 <classname>gadget::InputMixer<S,T></classname>, it is highly 920 recommended that one of the predefined instantiations be used to 921 ensure that a known type is used as a base class for the device 922 driver. The order that the classes are listed in the 923 <classname>gadget::InputMixer<S,T></classname> is critical 924 because the Remote Input Manager only knows about certain 925 instantiations. If an unexpected instantiation is encountered, 926 problems will occur. In the best case, the device data will not be 927 shared in a cluster configuration. In the worst case, the 928 application will crash. The known instantiations are all listed in 929 the file <filename>gadget/Type/InputBaseTypes.h</filename>.</para> 930 931 <caution> 932 <para>The Input Mixer may not be a long-term solution, though 933 it has been in place for quite a while. A future version of 934 Gadgeteer may do away with 935 <classname>gadget::InputMixer<S,T></classname>, and as 936 such, driver authors should be aware of potential API changes 937 in the future.</para> 938 </caution> 925 939 </section> 926 940 </chapter> … … 1173 1187 <para>For example, to make a driver that registers button 1174 1188 presses, derive from 1175 <classname>gadget::Digital</classname>:</para> 1189 <classname>gadget::input_digital_t</classname> (the 1190 <classname>gadget::InputMixer<S,T></classname> 1191 instantiation that includes only 1192 <classname>gadget::Digital</classname>):</para> 1176 1193 1177 1194 <programlisting>class ButtonDevice 1178 : public gadget:: InputMixer<gadget::Input, gadget::Digital></programlisting>1195 : public gadget::input_digital_t</programlisting> 1179 1196 1180 1197 <para>Suppose that a game controller driver supporting buttons … … 1183 1200 axes. Since the device is both digital and analog, its class 1184 1201 must derive from both <classname>gadget::Digital</classname> 1185 and <classname>gadget::Analog</classname> using C++ multiple 1186 inheritance:</para> 1202 and <classname>gadget::Analog</classname> using the appropriate 1203 <classname>gadget::InputMixer<S,T></classname> 1204 instantiation:</para> 1187 1205 1188 1206 <programlisting>class JoystickDevice 1189 : public gadget::InputMixer<gadget::Input, 1190 gadget::InputMixer<gadget::Digital, 1191 gadget::Analog> ></programlisting> 1207 : public gadget::input_digital_analog_t</programlisting> 1192 1208 1193 1209 <para>Using the type <classname>ButtonDevice</classname> as … … 1297 1313 { 1298 1314 1299 void nonMemberSampleFunction( void* arg)1315 void nonMemberSampleFunction(ButtonDevice* devPtr) 1300 1316 { 1301 ButtonDevice* dev_ptr = static_cast<ButtonDevice*>(arg); 1302 1303 // Keep working until mRunning becomes false. 1304 while ( dev_ptr->isRunning() ) 1317 // Keep working until isRunning() returns false. 1318 while ( devPtr->isRunning() ) 1305 1319 { 1306 dev _ptr->sample();1320 devPtr->sample(); 1307 1321 } 1308 1322 } … … 1313 1327 { 1314 1328 mRunning = true; 1315 mThread = new vpr::Thread( nonMemberSampleFunction, (void*) this);1329 mThread = new vpr::Thread(boost::bind(nonMemberSampleFunction, this)); 1316 1330 return true; 1317 1331 }</programlisting> … … 1329 1343 1330 1344 private: 1331 static void staticMemberSampleFunction( void* arg);1345 static void staticMemberSampleFunction(ButtonDevice* devPtr); 1332 1346 ... 1333 1347 }; … … 1336 1350 { 1337 1351 mRunning = true; 1338 mThread = new vpr::Thread(staticMemberSampleFunction, (void*) this); 1352 mThread = 1353 new vpr::Thread(boost::bind(ButtonDevice::staticMemberSampleFunction, 1354 this)); 1339 1355 return true; 1340 1356 } … … 1358 1374 { 1359 1375 mRunning = true; 1360 vpr::ThreadMemberFunctor<ButtonDevice>* functor = 1361 new vpr::ThreadMemberFunctor<ButtonDevice>( 1362 this, &ButtonDevice::membersampleFunction, NULL 1363 ); 1364 mThread = new vpr::Thread(functor); 1376 mThread = 1377 new vpr::Thread(boost::bind(&ButtonDevice::memberSampleFunction, this); 1365 1378 return true; 1366 1379 } 1367 1380 1368 void ButtonDevice::memberSampleFunction( void* arg)1381 void ButtonDevice::memberSampleFunction() 1369 1382 { 1370 1383 // Keep working until mRunning becomes false. … … 2366 2379 button.</para> 2367 2380 2381 <important> 2382 <para>This implementation is trivial by design. A more 2383 appropriate implementation for this case would not use a thread 2384 for sampling and would instead call 2385 <methodname>sample()</methodname> from 2386 <methodname>updateData()</methodname> so that only one sample 2387 is recorded per frame. The reason for doing this is because 2388 this <quote>driver</quote> is not I/O-bound and instead just 2389 adds a value to the digital sample buffer every time 2390 <methodname>sample()</methodname> is invoked.</para> 2391 </important> 2392 2368 2393 <example id="example.ButtonDevice.h"> 2369 <title><filename>ButtonDevice.h</filename></title> 2370 2371 <programlisting linenumbering="numbered"> 2372 #ifndef _EXAMPLE_BUTTON_DEVICE_H_ 2394 <title><filename>buttondevice.h</filename></title> 2395 2396 <programlisting linenumbering="numbered">#ifndef _EXAMPLE_BUTTON_DEVICE_H_ 2373 2397 #define _EXAMPLE_BUTTON_DEVICE_H_ 2374 2398 … … 2460 2484 /** 2461 2485 * Our sampling function that is executed by the spawned 2462 * sample thread. This function is declared as a static member 2463 * of ButtonDevice. It simply calls ButtonDevice::sample() 2464 * over and over. 2486 * sample thread. This function simply calls 2487 * ButtonDevice::sample() over and over. 2465 2488 */ 2466 static void threadedSampleFunction(void* classPointer);2489 void threadedSampleFunction(); 2467 2490 2468 2491 vpr::Thread* mSampleThread; … … 2483 2506 2484 2507 #include <vector> 2508 #include <boost/bind.hpp> 2485 2509 2486 2510 #include <vpr/vpr.h> … … 2539 2563 bool ButtonDevice::startSampling() 2540 2564 { 2541 mRunning = true; 2542 mSampleThread = new vpr::Thread(threadedSampleFunction, 2543 (void*) this); 2544 2545 if ( ! mSampleThread->valid() ) 2565 mRunning = false; 2566 2567 try 2546 2568 { 2547 mRunning = false; 2548 return false; // thread creation failed 2569 mSampleThread = 2570 new vpr::Thread(boost::bind(&ButtonDevice::threadedSampleFunction, 2571 this)); 2572 mRunning = true; 2549 2573 } 2550 else2574 catch (vpr::Exception& ex) 2551 2575 { 2552 return true; // thread creation success 2576 std::cerr << "Failed to spawn sample thread!\n" << ex.what() 2577 << std::endl; 2553 2578 } 2579 2580 return mRunning; 2554 2581 } 2555 2582 … … 2599 2626 2600 2627 // Our sampling function that is executed by the spawned sample 2601 // thread. This function is declared as a static member of 2602 // ButtonDevice. It simply calls ButtonDevice::sample() over and 2603 // over. 2604 void ButtonDevice::threadedSampleFunction(void* classPointer) 2628 // thread. 2629 void ButtonDevice::threadedSampleFunction() 2605 2630 { 2606 ButtonDevice* this_ptr =2607 static_cast<ButtonDevice*>(classPointer);2608 2609 2631 // spin until someone kills "mSampleThread" 2610 while ( this_ptr->mRunning )2632 while ( mRunning ) 2611 2633 { 2612 this_ptr->sample();2634 sample(); 2613 2635 } 2614 2636 }</programlisting> … … 2668 2690 SRCS= buttondevice.cpp 2669 2691 2670 include $(GADGET_BASE_DIR)/share/gadgeteer/gadget.driver.mk</programlisting> 2692 GADGET_BASE_DIR=$(shell flagpoll gadgeteer --get-prefix) 2693 GADGET_VERSION= $(shell flagpoll gadgeteer --modversion) 2694 2695 include $(GADGET_BASE_DIR)/share/gadgeteer-$(GADGET_VERSION)/gadget.driver.mk</programlisting> 2671 2696 </example> 2672 2697 … … 2701 2726 Optimization="0" 2702 2727 AdditionalIncludeDirectories="&quot;$(VJ_BASE_DIR)\include&quot;;&quot;$(VJ_DEPS_DIR)\include&quot;" 2703 PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;_USRDLL;_GADGET_DRIVER_BUILD_" 2728 PreprocessorDefinitions="WIN32;JUGGLER_DEBUG;_CONSOLE;_USRDLL;_GADGET_DRIVER_BUILD_" 2729 MinimalRebuild="FALSE" 2730 RuntimeLibrary="2" 2731 BufferSecurityCheck="FALSE" 2732 RuntimeTypeInfo="TRUE" 2733 UsePrecompiledHeader="0" 2734 WarningLevel="3" 2735 Detect64BitPortabilityProblems="TRUE" 2736 DebugInformationFormat="1" 2737 DisableSpecificWarnings="4244;4251;4267;4275;4290;4312;4800"/> 2738 <Tool 2739 Name="VCCustomBuildTool"/> 2740 <Tool 2741 Name="VCLinkerTool" 2742 AdditionalDependencies="libnspr4.lib libplc4.lib ws2_32.lib $(NOINHERIT)" 2743 OutputFile="$(OutDir)/button_drv_g.dll" 2744 LinkIncremental="1" 2745 AdditionalLibraryDirectories="&quot;$(VJ_BASE_DIR)\lib&quot;;&quot;$(VJ_DEPS_DIR)\lib&quot;" 2746 GenerateDebugInformation="FALSE" 2747 ProgramDatabaseFile="$(OutDir)/button_drv_g.pdb" 2748 SubSystem="1" 2749 ImportLibrary="$(OutDir)/button_drv_g.lib" 2750 TargetMachine="1"/> 2751 <Tool 2752 Name="VCMIDLTool"/> 2753 <Tool 2754 Name="VCPostBuildEventTool"/> 2755 <Tool 2756 Name="VCPreBuildEventTool"/> 2757 <Tool 2758 Name="VCPreLinkEventTool"/> 2759 <Tool 2760 Name="VCResourceCompilerTool"/> 2761 <Tool 2762 Name="VCWebServiceProxyGeneratorTool"/> 2763 <Tool 2764 Name="VCWebDeploymentTool"/> 2765 </Configuration> 2766 <Configuration 2767 Name="DebugRt|Win32" 2768 OutputDirectory="DebugDLL" 2769 IntermediateDirectory="DebugDLL" 2770 ConfigurationType="2" 2771 CharacterSet="2"> 2772 <Tool 2773 Name="VCCLCompilerTool" 2774 Optimization="0" 2775 AdditionalIncludeDirectories="&quot;$(VJ_BASE_DIR)\include&quot;;&quot;$(VJ_DEPS_DIR)\include&quot;" 2776 PreprocessorDefinitions="WIN32;JUGGLER_DEBUG;_CONSOLE;_USRDLL;_GADGET_DRIVER_BUILD_" 2704 2777 MinimalRebuild="FALSE" 2705 2778 BasicRuntimeChecks="3" … … 2716 2789 <Tool 2717 2790 Name="VCLinkerTool" 2718 AdditionalDependencies=" gadget_d.lib jccl_d.lib vpr_d.liblibnspr4.lib libplc4.lib ws2_32.lib $(NOINHERIT)"2791 AdditionalDependencies="libnspr4.lib libplc4.lib ws2_32.lib $(NOINHERIT)" 2719 2792 OutputFile="$(OutDir)/button_drv_d.dll" 2720 2793 LinkIncremental="1" … … 2752 2825 OmitFramePointers="TRUE" 2753 2826 AdditionalIncludeDirectories="&quot;$(VJ_BASE_DIR)\include&quot;;&quot;$(VJ_DEPS_DIR)\include&quot;" 2754 PreprocessorDefinitions="WIN32; _OPT;NDEBUG;_CONSOLE;_USRDLL;_GADGET_DRIVER_BUILD_"2827 PreprocessorDefinitions="WIN32;JUGGLER_OPT;NDEBUG;_CONSOLE;_USRDLL;_GADGET_DRIVER_BUILD_" 2755 2828 StringPooling="TRUE" 2756 2829 MinimalRebuild="FALSE" … … 2768 2841 <Tool 2769 2842 Name="VCLinkerTool" 2770 AdditionalDependencies=" gadget.lib jccl.lib vpr.liblibnspr4.lib libplc4.lib ws2_32.lib $(NOINHERIT)"2843 AdditionalDependencies="libnspr4.lib libplc4.lib ws2_32.lib $(NOINHERIT)" 2771 2844 OutputFile="$(OutDir)/button_drv.dll" 2772 2845 LinkIncremental="1"
