Symbian3/SDK/Source/GUID-6590B534-D976-5305-BE95-48DD05120DFB.dita
changeset 0 89d6a7a84779
child 2 ebc84c812384
equal deleted inserted replaced
-1:000000000000 0:89d6a7a84779
       
     1 <?xml version="1.0" encoding="utf-8"?>
       
     2 <!-- Copyright (c) 2007-2010 Nokia Corporation and/or its subsidiary(-ies) All rights reserved. -->
       
     3 <!-- This component and the accompanying materials are made available under the terms of the License 
       
     4 "Eclipse Public License v1.0" which accompanies this distribution, 
       
     5 and is available at the URL "http://www.eclipse.org/legal/epl-v10.html". -->
       
     6 <!-- Initial Contributors:
       
     7     Nokia Corporation - initial contribution.
       
     8 Contributors: 
       
     9 -->
       
    10 <!DOCTYPE concept
       
    11   PUBLIC "-//OASIS//DTD DITA Concept//EN" "concept.dtd">
       
    12 <concept id="GUID-6590B534-D976-5305-BE95-48DD05120DFB" xml:lang="en"><title>Miscellaneous
       
    13 Topics</title><prolog><metadata><keywords/></metadata></prolog><conbody>
       
    14 <ul>
       
    15 <li id="GUID-6830949E-0825-5E13-9B3E-86B5014F4B77"><p><xref href="GUID-6590B534-D976-5305-BE95-48DD05120DFB.dita#GUID-6590B534-D976-5305-BE95-48DD05120DFB/GUID-624B9EC6-7C8E-5408-AAF3-F799314B6D7A">Poll using select</xref>  </p> <ul>
       
    16 <li id="GUID-7E0FA15B-8AFB-59DD-B577-34905989D316"><p><xref href="GUID-6590B534-D976-5305-BE95-48DD05120DFB.dita#GUID-6590B534-D976-5305-BE95-48DD05120DFB/GUID-6B8931EB-7AB9-588C-B419-0CD4BA048397">Monitoring two pipes using select()</xref>  </p> </li>
       
    17 </ul> </li>
       
    18 <li id="GUID-245A31A4-4C38-54F4-9ACC-92285C12966E"><p><xref href="GUID-6590B534-D976-5305-BE95-48DD05120DFB.dita#GUID-6590B534-D976-5305-BE95-48DD05120DFB/GUID-7582B2CB-AAC8-5E41-ADE1-76C12B691E10">Socket IOCtl options</xref>  </p> </li>
       
    19 <li id="GUID-1A2BDA7D-2DE4-52AE-ACD3-12D1A6311A88"><p><xref href="GUID-6590B534-D976-5305-BE95-48DD05120DFB.dita#GUID-6590B534-D976-5305-BE95-48DD05120DFB/GUID-9BF9562E-5831-5A7F-90A1-87BDE1CFBA54">Mathematical functions</xref>  </p> </li>
       
    20 <li id="GUID-A6183A50-BFBA-573B-B2BC-68BE637D7DF5"><p><xref href="GUID-6590B534-D976-5305-BE95-48DD05120DFB.dita#GUID-6590B534-D976-5305-BE95-48DD05120DFB/GUID-DA65E8FA-E20B-5572-AEC9-20AB140DF33A">Error handling and cleanup</xref>  </p> <ul>
       
    21 <li id="GUID-ADB0AC3E-FB59-52DC-B151-A4551467CBA0"><p><xref href="GUID-6590B534-D976-5305-BE95-48DD05120DFB.dita#GUID-6590B534-D976-5305-BE95-48DD05120DFB/GUID-D8DB43BD-9D19-5A78-8E37-6699653D047A">Mapping P.I.P.S. error codes to Symbian platform error codes</xref>  </p> </li>
       
    22 </ul> </li>
       
    23 <li id="GUID-EA748131-29ED-5D32-B1C2-F948ABEA6584"><p><xref href="GUID-6590B534-D976-5305-BE95-48DD05120DFB.dita#GUID-6590B534-D976-5305-BE95-48DD05120DFB/GUID-CF52A59F-FD04-5043-A526-05545E11F0F5">System logger</xref>  </p> </li>
       
    24 <li id="GUID-1C98EDF4-C7BD-5CC8-90EB-D35B759280CD"><p><xref href="GUID-6590B534-D976-5305-BE95-48DD05120DFB.dita#GUID-6590B534-D976-5305-BE95-48DD05120DFB/GUID-8C951D9F-DE32-5201-90F2-45EB442F9FFC">Pthread barriers, rwlocks and spinlocks</xref>  </p> </li>
       
    25 <li id="GUID-AFB6D3DE-B1ED-51CF-B02D-BBF1958F6357"><p><xref href="GUID-6590B534-D976-5305-BE95-48DD05120DFB.dita#GUID-6590B534-D976-5305-BE95-48DD05120DFB/GUID-777FDBF9-4B80-5B58-88F3-E78DBDB89021">Command line shell</xref>  </p> </li>
       
    26 <li id="GUID-2357315B-21A6-5A9D-8D8D-B72043376F41"><p><xref href="GUID-6590B534-D976-5305-BE95-48DD05120DFB.dita#GUID-6590B534-D976-5305-BE95-48DD05120DFB/GUID-98FE0A61-A9F6-5216-A01F-A213F33D3173">User interfaces</xref>  </p> </li>
       
    27 <li id="GUID-EB745371-907B-595B-AD2F-0FB0B7991066"><p><xref href="GUID-6590B534-D976-5305-BE95-48DD05120DFB.dita#GUID-6590B534-D976-5305-BE95-48DD05120DFB/GUID-3CA8FF29-79B4-5D43-8A23-EDB136BF7A8F">One Definition Rule - warning</xref>  </p> </li>
       
    28 </ul>
       
    29 <section id="GUID-624B9EC6-7C8E-5408-AAF3-F799314B6D7A"><title>Poll using
       
    30 select</title> <p>The <xref href="GUID-8B4D4123-8146-3157-B171-28F71E0C8E4A.dita"><apiname>select()</apiname></xref> function call provides functionality
       
    31 to scan descriptors for a ready event. The <codeph>select()</codeph> call
       
    32 requires the system to scan through a bit mask of a file descriptor set against
       
    33 its list of open descriptors to check for ready events, only stopping when
       
    34 it reaches a maximum descriptor value. For a system with a relatively small
       
    35 number of open descriptors this is quite efficient but for a large amount
       
    36 of descriptors can be overly burdensome. </p> <p>The Symbian P.I.P.S. libraries
       
    37 are not expected to be dealing with a very large number of file descriptors
       
    38 and so <codeph>select()</codeph> should be satisfactory for any applications
       
    39 on a phone. </p> <p> <b>Note:</b> P.I.P.S. does not support the <codeph>poll()</codeph> function. </p> <p id="GUID-6B8931EB-7AB9-588C-B419-0CD4BA048397"><b>Monitoring two pipes using
       
    40 select()</b> </p> <p>The following code segment shows the usage of the <codeph>select()</codeph> function: </p> <codeblock id="GUID-36B78671-0A09-529C-B167-8F3E10C2CCB5" xml:space="preserve">Int main(int argc, char **argv)
       
    41 {
       
    42    FILE* ChildProcessStream1;
       
    43    FILE* ChildProcessStream2;
       
    44    int ChildProcessFD1;
       
    45    int ChildProcessFD2;
       
    46    fd_set SelectFDs;
       
    47    int MaxFD;
       
    48    struct timeval timeout;
       
    49    int Ret;
       
    50 
       
    51    //Create child process 1 using popen(). 
       
    52    ChildProcessStream1 = popen("/root/PortDoc/Example7_c/Symbian/Child/ChildProg", "r");
       
    53    if(ChildProcessStream1 == NULL)
       
    54    {
       
    55       printf("\n Failure to create child process 1 with popen()\n");
       
    56       return EXIT_FAILURE;
       
    57    }
       
    58 
       
    59    //Create child process 2 using popen(). 
       
    60    ChildProcessStream2 = popen("/root/PortDoc/Example7_c/Symbian/Child/ChildProg", "r");
       
    61    if(ChildProcessStream2 == NULL)
       
    62    {
       
    63       printf("\n Failure to create child process 2 with popen()\n");
       
    64       return EXIT_FAILURE;
       
    65    }
       
    66 
       
    67    //Convert streams to file descriptors
       
    68    ChildProcessFD1 = fileno(ChildProcessStream1);
       
    69    ChildProcessFD2 = fileno(ChildProcessStream2);
       
    70 
       
    71    //Setup the select set
       
    72    FD_ZERO(&amp;SelectFDs);
       
    73    FD_SET(ChildProcessFD1, &amp;SelectFDs);
       
    74    MaxFD = ChildProcessFD1;
       
    75    FD_SET(ChildProcessFD2, &amp;SelectFDs);
       
    76    
       
    77    //Calculate the largest Descriptor
       
    78    if (ChildProcessFD2 &gt; MaxFD)
       
    79       MaxFD = ChildProcessFD2;
       
    80    
       
    81    //Setup a time out value in case neither return in a sufficient time
       
    82    timeout.tv_sec = 3;
       
    83    timeout.tv_usec = 0;
       
    84    
       
    85    //Issue select request
       
    86    Ret = select(MaxFD + 1, &amp;SelectFDs, NULL, NULL, &amp;timeout);
       
    87    if (Ret == -1)
       
    88    {
       
    89       //Error occurred
       
    90       printf("\nCould not poll, error=%d",errno);    
       
    91       return EXIT_FAILURE;
       
    92    }
       
    93    else if (Ret == 0)
       
    94    {
       
    95       //Timed out
       
    96       printf("\nTimed Out");    
       
    97    }
       
    98    else
       
    99    {
       
   100       //Create a receive buffer, and zero contents before receiving.
       
   101       Char RxBuffer[100];
       
   102       memset(RxBuffer,0,sizeof(RxBuffer));
       
   103 
       
   104       if (FD_ISSET(ChildProcessFD1, &amp;SelectFDs))
       
   105       {
       
   106          //Wait for data from child process 1. Child sends a string.
       
   107          Int nbytes = read(ChildProcessFD1,RxBuffer,sizeof(RxBuffer));
       
   108          printf("\nMessage Received from Child1 First =%s",RxBuffer);
       
   109       }
       
   110       else if (FD_ISSET(ChildProcessFD2, &amp;SelectFDs))
       
   111       {
       
   112          //Wait for data from child process 2. Child sends a string.
       
   113          Int nbytes = read(ChildProcessFD2,RxBuffer,sizeof(RxBuffer));
       
   114          printf("\nMessage Received from Child2 First =%s",RxBuffer);
       
   115       }
       
   116    }
       
   117 
       
   118    //Wait for Child Process to complete
       
   119    pclose(ChildProcessStream1);
       
   120    pclose(ChildProcessStream2);
       
   121 
       
   122    return EXIT_SUCCESS;
       
   123 }</codeblock> </section>
       
   124 <section id="GUID-7582B2CB-AAC8-5E41-ADE1-76C12B691E10"><title>Socket IOCtl
       
   125 options</title> <p>The underlying implementation of sockets on Symbian platform
       
   126 imposes some restrictions on the socket options available in P.I.P.S. and
       
   127 has also resulted in some new non-standard options to be created. </p> <p>The
       
   128 introduction of multi-homing (single link, multiple IP addresses) on Symbian
       
   129 phones and the various methods of connecting to networks, such as Wi-Fi and
       
   130 3G, with their varying degrees of cost to the user have made it important
       
   131 to be able to choose which interface or access point is used to route socket
       
   132 traffic. The Symbian <xref href="GUID-BED8A733-2ED7-31AD-A911-C1F4707C67FD.dita"><apiname>RConnection</apiname></xref> class provides this functionality,
       
   133 and is exposed in P.I.P.S. using some extra IOCtl options. </p> <p>The list
       
   134 of socket options available in P.I.P.S. are as follows: </p> <table id="GUID-B753C24D-597E-53AB-A633-C128C7316514">
       
   135 <tgroup cols="3"><colspec colname="col0"/><colspec colname="col1"/><colspec colname="col2"/>
       
   136 <tbody>
       
   137 <row>
       
   138 <entry><p> <b>Socket Option</b>  </p> </entry>
       
   139 <entry><p> <b>New</b>  </p> </entry>
       
   140 <entry><p> <b>Description</b>  </p> </entry>
       
   141 </row>
       
   142 <row>
       
   143 <entry><p>SIOCADDRT </p> </entry>
       
   144 <entry><p>Yes </p> </entry>
       
   145 <entry><p>Adds an entry to the interface routing table using the parameters
       
   146 in the <codeph>rtentry</codeph> structure. </p> </entry>
       
   147 </row>
       
   148 <row>
       
   149 <entry><p>SIOCATMARK </p> </entry>
       
   150 <entry><p>No </p> </entry>
       
   151 <entry><p>Determines whether the read pointer is currently pointing to the
       
   152 logical mark in the data stream, testing whether the next read will be Out-of-Band
       
   153 data or not. </p> </entry>
       
   154 </row>
       
   155 <row>
       
   156 <entry><p>SIOCDELRT </p> </entry>
       
   157 <entry><p>Yes </p> </entry>
       
   158 <entry><p>Deletes an entry from the interface routing table using the parameters
       
   159 in the <codeph>rtentry</codeph> structure. </p> </entry>
       
   160 </row>
       
   161 <row>
       
   162 <entry><p>SIOCGIFACTIVECONF </p> </entry>
       
   163 <entry><p>Yes </p> </entry>
       
   164 <entry><p>Gets a list of interfaces/access points started by P.I.P.S. in an <codeph>ifconf</codeph> structure. </p> </entry>
       
   165 </row>
       
   166 <row>
       
   167 <entry><p>SIOCGIFADDR </p> </entry>
       
   168 <entry><p>Yes </p> </entry>
       
   169 <entry><p>Gets the interface address. This is valid only for sockets with
       
   170 address family AF_INET. </p> </entry>
       
   171 </row>
       
   172 <row>
       
   173 <entry><p>SIOCGIFCONF </p> </entry>
       
   174 <entry><p>No </p> </entry>
       
   175 <entry><p>Gets a list of available interfaces/access points in an <codeph>ifconf</codeph> structure. </p> </entry>
       
   176 </row>
       
   177 <row>
       
   178 <entry><p>SIOCGIFHWADDR </p> </entry>
       
   179 <entry><p>Yes </p> </entry>
       
   180 <entry><p>Gets the interface hardware address in an <codeph>ifreq</codeph> structure. </p> </entry>
       
   181 </row>
       
   182 <row>
       
   183 <entry><p>SIOCGIFINDEX </p> </entry>
       
   184 <entry><p>Yes </p> </entry>
       
   185 <entry><p>Sets the index of an interface/access point from a name in an <codeph>ifreq</codeph> structure. </p> </entry>
       
   186 </row>
       
   187 <row>
       
   188 <entry><p>SIOCGIFNUM </p> </entry>
       
   189 <entry><p>Yes </p> </entry>
       
   190 <entry><p>Return the total number of IP interfaces configured in the system. </p> </entry>
       
   191 </row>
       
   192 <row>
       
   193 <entry><p>SIOCIFACTIVESTART </p> </entry>
       
   194 <entry><p>Yes </p> </entry>
       
   195 <entry><p>Attempts to start a sub-connection on an available interface/access
       
   196 point using the parameters in an <codeph>ifreq</codeph> structure. </p> </entry>
       
   197 </row>
       
   198 <row>
       
   199 <entry><p>SIOCIFSTART </p> </entry>
       
   200 <entry><p>Yes </p> </entry>
       
   201 <entry><p>Attempts to start an interface/access point using the parameters
       
   202 in an <codeph>ifreq</codeph> structure. </p> </entry>
       
   203 </row>
       
   204 <row>
       
   205 <entry><p>SIOCIFSTOP </p> </entry>
       
   206 <entry><p>Yes </p> </entry>
       
   207 <entry><p>Stops a previously started interface or sub-connection. </p> </entry>
       
   208 </row>
       
   209 <row>
       
   210 <entry><p>SIOCSIFNAME </p> </entry>
       
   211 <entry><p>No </p> </entry>
       
   212 <entry><p>Sets the desired interface/access point name to start in an <codeph>ifreq</codeph> structure. </p> </entry>
       
   213 </row>
       
   214 </tbody>
       
   215 </tgroup>
       
   216 </table> <p>The follow code for a function shows how to start an interface
       
   217 called "3G Access Point" and return the created socket. </p> <codeblock id="GUID-94D8CA06-366E-5697-A72B-891C07F21F8E" xml:space="preserve">int opensocket()
       
   218 {
       
   219   int Sock;
       
   220   struct ifreq Ifr;
       
   221   char AccessPoint[]="3G Access Point";
       
   222 
       
   223   //Open the socket
       
   224   Sock = socket(AF_INET, SOCK_STREAM, 0);
       
   225   if (Sock &lt; 0) 
       
   226   {
       
   227     printf("\nCannot open socket, error=%d",errno);
       
   228     return -1;
       
   229   }
       
   230 
       
   231   //Set up the interface request structure
       
   232   bzero(&amp;Ifr, sizeof(Ifr));
       
   233   strcpy(Ifr.ifr_name, AccessPoint);
       
   234     
       
   235   //Set the requested interface name
       
   236   if (ioctl(Sock, SIOCSIFNAME, &amp;Ifr))
       
   237   {
       
   238     printf("\nCannot set the interface name, error=%d",errno);
       
   239     close(Sock);
       
   240     return -1;
       
   241   }
       
   242 
       
   243   //Start the interface
       
   244   if (ioctl(Sock, SIOCIFSTART, &amp;Ifr))
       
   245   {
       
   246     printf("\nCannot start the interface, error=%d",errno);
       
   247     close(Sock);
       
   248     return -1;
       
   249   }
       
   250 
       
   251   //Return the opened socket
       
   252   return Sock;
       
   253 }</codeblock> </section>
       
   254 <section id="GUID-9BF9562E-5831-5A7F-90A1-87BDE1CFBA54"><title>Mathematical
       
   255 functions</title> <p>Symbian platform does not have any support for long doubles
       
   256 so any P.I.P.S. programs which call long double versions of APIs will actually
       
   257 invoke the double version of the API. </p> <p>Symbian platform supports the
       
   258 use of a hardware floating point co-processor, however not all phones incorporate
       
   259 an FPU (Floating Point Unit) and rely on software emulation of floating point
       
   260 operations. Phones and computers equipped with an FPU provide faster and more
       
   261 accurate floating point operations. </p> <p>Symbian platform does not support
       
   262 complex numbers so the P.I.P.S. libraries are not able to offer the POSIX
       
   263 complex number APIs. </p> <p> <b>Note:</b> The mathematical functions are
       
   264 included in the <filepath>libm.dll</filepath> file. </p> </section>
       
   265 <section id="GUID-DA65E8FA-E20B-5572-AEC9-20AB140DF33A"><title> Error handling
       
   266 and cleanup</title> <p>It is important that Symbian platform error codes do
       
   267 not reach any ported application code. P.I.P.S. logically maps the native
       
   268 OS error codes with the corresponding POSIX <codeph>errno</codeph> values
       
   269 as per the standard. So, ported programs will not usually have to alter their
       
   270 error checking/handling. </p> <p id="GUID-D8DB43BD-9D19-5A78-8E37-6699653D047A"><b>Mapping
       
   271 P.I.P.S. error codes to Symbian platform error codes</b> </p> <p>Porting your
       
   272 application to Symbian platform requires 'translating' Symbian platform error
       
   273 codes to POSIX error codes. <xref href="GUID-C197C9A7-EA05-3F24-9854-542E984C612D.dita#GUID-C197C9A7-EA05-3F24-9854-542E984C612D/GUID-B00F7659-9C31-36CD-896A-40887DECEA4B"><apiname>User::Leaves()</apiname></xref> from native
       
   274 Symbian APIs are trapped in P.I.P.S.. Calls to P.I.P.S. APIs from user code
       
   275 need not be wrapped in <xref href="GUID-3AD20E0C-F364-533F-9FBC-227478CA9982.dita">TRAP</xref> s. </p> <p>Occasionally
       
   276 errors may be generated by the underlying Symbian platform that cannot be
       
   277 translated to POSIX error codes, in which case the error variable <codeph>errno</codeph> will
       
   278 be out of the usual range of values, above the maximum value of <codeph>__EMAXERRNO</codeph> or <codeph>124</codeph>. </p> <p>The
       
   279 Symbian platform error code can be calculated using the following formula: </p> <codeblock id="GUID-A2F7B744-4B73-56AB-BA06-7C83333ADC5D" xml:space="preserve">Symbian Error Code = -(errno - __EMAXERRNO)</codeblock> <p>Error
       
   280 codes are defined in the <filepath>errno.h</filepath> file. </p> </section>
       
   281 <section id="GUID-CF52A59F-FD04-5043-A526-05545E11F0F5"><title>System logger</title> <p>P.I.P.S.
       
   282 does not supply a system logger for use with <xref href="GUID-0138AF2F-50A6-3FAD-8AE9-FDBFD66E5EF5.dita"><apiname>openlog()</apiname></xref>, <xref href="GUID-CCBCF015-F7CF-3A55-A723-0BC4B4DC758C.dita"><apiname>syslog()</apiname></xref> and <xref href="GUID-57C7FF8B-7EB3-35BE-BC9B-5FD6ABEE6225.dita"><apiname>closelog()</apiname></xref>.
       
   283 Instead, a rudimentary selection of functions which log to a file can be written
       
   284 as demonstrated by the following example. </p> <codeblock id="GUID-EE476405-2657-5827-81F4-DD5A29BF9F35" xml:space="preserve">//define maximum length of identifier
       
   285 #define SysLogMax 80
       
   286 
       
   287 //logging file and identifier
       
   288 FILE* fSysLog = NULL;
       
   289 char fSysLogIdent[SysLogMax];
       
   290 
       
   291 //close the log file
       
   292 void my_closelog()
       
   293 {
       
   294    //close the log file if it is open
       
   295    if (fSysLog)
       
   296    {
       
   297       fclose(fSysLog);
       
   298       fSysLog = NULL;
       
   299    }
       
   300    fSysLogIdent[0] = '\0';
       
   301 }
       
   302 
       
   303 //open a new log file
       
   304 int my_openlog(const char *ident)
       
   305 {
       
   306    //close the log file if it is open
       
   307    if (fSysLog)
       
   308       my_closelog();    
       
   309     
       
   310    //make the logging directory
       
   311    mkdir("/syslog/", S_IWUSR | S_IRUSR | S_IXUSR);
       
   312     
       
   313    //open a new log file
       
   314    fSysLog = fopen("/syslog/syslog.log", "a");
       
   315     
       
   316    //return if the log file did not open
       
   317    if (!fSysLog)
       
   318       return -1;
       
   319     
       
   320    //set the identifier
       
   321    if (!ident)
       
   322       fSysLogIdent[0] = '\0';
       
   323    else    
       
   324       strncpy(fSysLogIdent, ident, SysLogMax);
       
   325     
       
   326    return 0;
       
   327 }
       
   328 
       
   329 //output a string to the log file with a variable argument list
       
   330 void my_vsyslog(const char *format, va_list formatlist)
       
   331 {
       
   332    //open a log file if one does not exist
       
   333    if (!fSysLog)
       
   334    {
       
   335       my_openlog(NULL);    
       
   336    }
       
   337     
       
   338    //check if there is a log file 
       
   339    if (fSysLog)
       
   340    {
       
   341       //print out the logging identifier if one exists
       
   342       if (strlen(fSysLogIdent))
       
   343       {
       
   344          fprintf(fSysLog, "%s ", fSysLogIdent);
       
   345       }
       
   346         
       
   347       //print out the logging string
       
   348       vfprintf(fSysLog, format, formatlist);    
       
   349       fprintf(fSysLog, "\r\n");    
       
   350    }
       
   351 }
       
   352 
       
   353 //output a string to the log file
       
   354 void my_syslog(const char *format, ...)
       
   355 {
       
   356    //create the variable argument list
       
   357    va_list formatlist;
       
   358    va_start(formatlist, format);
       
   359    my_vsyslog(format, formatlist);
       
   360    va_end(formatlist);
       
   361 }
       
   362 
       
   363 
       
   364 int main(int argc, char **argv)
       
   365 {
       
   366    //open the log file
       
   367    my_openlog("test");
       
   368    
       
   369    //log a line
       
   370    my_syslog("testing logging of the error number : %d", errno);
       
   371    
       
   372    //close the log
       
   373    my_closelog();
       
   374    
       
   375    return EXIT_SUCCESS;
       
   376 }</codeblock> </section>
       
   377 <section id="GUID-8C951D9F-DE32-5201-90F2-45EB442F9FFC"><title>Pthread barriers,
       
   378 rwlocks and spinlocks</title> <p>At present P.I.P.S. does not provide Pthread
       
   379 barriers, rwlocks or spinlocks, but there are techniques which can be used
       
   380 to implement the functionality using semaphores, mutexes and conditional variables. </p> <p>The
       
   381 following code sample (originally taken from <xref href="http://heather.cs.ucdavis.edu/matloff/public_html/158/PLN/ParProcIntro.pdf" scope="external">http://heather.cs.ucdavis.edu/matloff/public_html/158/PLN/ParProcIntro.pdf</xref>)
       
   382 demonstrates an implementation of a simple Pthread barrier. </p> <codeblock id="GUID-A156CD2D-F212-57EA-A23A-C7B7478B431E" xml:space="preserve">struct barrier_t
       
   383 {
       
   384    //number of nodes to synchronise
       
   385    int nodes;
       
   386    //two counts to avoid race conditions
       
   387    int count[2];
       
   388    //which count to use
       
   389    int whichcount;
       
   390    //mutex to lock
       
   391    pthread_mutex_t lock;
       
   392    //condition to lock
       
   393    pthread_cond_t cv;
       
   394 };
       
   395 
       
   396 //initialize a barrier 
       
   397 void InitBarrier(struct barrier_t* PB, int nodes)
       
   398 {
       
   399    PB-&gt;nodes = nodes;
       
   400    PB-&gt;count[0] = 0;
       
   401    PB-&gt;count[1] = 0;
       
   402    PB-&gt;whichcount = 0;
       
   403    pthread_mutex_init(&amp;PB-&gt;lock, NULL);
       
   404    pthread_cond_init(&amp;PB-&gt;cv, NULL);
       
   405 }
       
   406 
       
   407 //destroy a barrier
       
   408 void DestroyBarrier(struct barrier_t* PB)
       
   409 {
       
   410    pthread_mutex_destroy(&amp;PB-&gt;lock);
       
   411    pthread_cond_destroy(&amp;PB-&gt;cv);
       
   412 }
       
   413 
       
   414 //wait for a barrier
       
   415 void WaitBarrier(struct barrier_t* PB)
       
   416 {
       
   417    int WhichCount, Count;
       
   418    
       
   419    //which counter variable to use
       
   420    WhichCount = PB-&gt;whichcount;
       
   421    
       
   422    //lock the mutex
       
   423    pthread_mutex_lock(&amp;PB-&gt;lock);
       
   424    
       
   425    //get the count of nodes
       
   426    Count = ++PB-&gt;count[WhichCount];
       
   427    
       
   428    //test whether it should block
       
   429    if (Count &lt; PB-&gt;nodes)
       
   430       pthread_cond_wait(&amp;PB-&gt;cv, &amp;PB-&gt;lock);
       
   431    else
       
   432    { 
       
   433       //reset the counter
       
   434       PB-&gt;count[WhichCount] = 0;
       
   435       PB-&gt;whichcount = 1 - WhichCount;
       
   436       
       
   437       //release the wait
       
   438       pthread_cond_broadcast(&amp;PB-&gt;cv);
       
   439    }
       
   440    
       
   441    //unlock the threads
       
   442    pthread_mutex_unlock(&amp;PB-&gt;lock);
       
   443 }</codeblock> <p>The following code was posted by Michael M. Lampkin as an
       
   444 open source implementation of Pthread spin threads. </p> <codeblock id="GUID-85F81360-113F-54DC-958E-7C76BC8BA98D" xml:space="preserve">/**********************************************************************
       
   445 BETA User Space spinlocks for POSIX systems lacking this functionality.
       
   446 Copyright ©) 2003-2006 Michael M. Lampkin 
       
   447 Contact at michael.lampkin&lt;at&gt;ieee.org
       
   448 This program is free software; you can redistribute it and/or modify
       
   449 it under the terms of the GNU General Public License version 2 as
       
   450 published by the Free Software Foundation.
       
   451 This program is distributed in the hope that it will be useful,
       
   452 but WITHOUT ANY WARRANTY; without even the implied warranty of
       
   453 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
       
   454 GNU General Public License for more details.
       
   455 You should have received a copy of the GNU General Public License
       
   456 version 2 along with this program; if not, write to the Free Software
       
   457 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301
       
   458 
       
   459 **********************************************************************/
       
   460 
       
   461 #define _POSIX_C_SOURCE 200112L
       
   462 #define _XOPEN_SOURCE 600
       
   463 
       
   464 #define SPINLOCK_SPIN_MAX 50
       
   465 
       
   466 /**
       
   467  Need this "unique" value that we can use to take any spinlock
       
   468  that has been initialized and identify attempts to call init
       
   469  multiple times without corresponding calls to destroy.  A hard
       
   470  coded value should be fine though still a 1 in 4 billion chance
       
   471  of collision with random data in un-inited spinlock.
       
   472 **/
       
   473 
       
   474 static long int spin_magic = 0x2FCD51F9L;
       
   475 
       
   476 /**
       
   477   The spinlock structure which should NEVER be manipulated
       
   478   by user code.
       
   479   owner:
       
   480     a pthread_t var indicating the current owner of the
       
   481     spinlock or filled with 0's if not owned
       
   482   mutex:
       
   483     the primary mutex that any incoming threads will spin on
       
   484     and attempt to obtain.
       
   485   magic:
       
   486     a field to hold a sentinel value indicating if the spinlock
       
   487     is initialized.
       
   488 **/
       
   489 
       
   490 typedef struct
       
   491 {
       
   492   pthread_t       owner;
       
   493   pthread_mutex_t mutex;
       
   494   long int        magic;
       
   495 } 
       
   496 spinlock;
       
   497 
       
   498 /**
       
   499  Function: spinlock_init
       
   500  Description:
       
   501    Initializes and allocates system resources to a
       
   502    spinlock structure.
       
   503  Parameters:
       
   504    spin - a pointer to the spinlock structure to
       
   505      be initialized.
       
   506    pshared - either PTHREAD_PROCESS_PRIVATE or
       
   507      PTHREAD_PROCESS_SHARED.  If the system does not
       
   508      support process shared mutexes or an unknown value
       
   509      is given then defaults internally to a private type
       
   510      with no error.
       
   511 **/
       
   512 
       
   513 int spinlock_init( spinlock * spin, int pshared )
       
   514 {
       
   515   int result;
       
   516   pthread_mutexattr_t attr;
       
   517 
       
   518   /* If already inited... race condition with destroy */
       
   519   if ( NULL == spin )
       
   520   {
       
   521     return EINVAL;
       
   522   }
       
   523 
       
   524   if ( spin_magic == spin-&gt;magic )
       
   525   {
       
   526     return EBUSY;
       
   527   }
       
   528 
       
   529   ( void ) memset( &amp; spin-&gt;owner, 0, sizeof( pthread_t ) );
       
   530 
       
   531   /* Set our process sharing attribute - default to PRIVATE */
       
   532   result = pthread_mutexattr_init( &amp; attr );
       
   533 
       
   534   if ( 0 == result )
       
   535   {
       
   536     if ( 0 &lt; sysconf( _SC_THREAD_PROCESS_SHARED ) )
       
   537     {
       
   538       if( PTHREAD_PROCESS_SHARED == pshared )
       
   539       {
       
   540         result = pthread_mutexattr_setpshared( &amp; attr, pshared );
       
   541       }
       
   542       else
       
   543       {
       
   544         result = pthread_mutexattr_setpshared( &amp; attr, PTHREAD_PROCESS_PRIVATE );
       
   545       }
       
   546     }
       
   547   }
       
   548 
       
   549   /* Need to add this to prevent recursive mutex default on some sys */
       
   550   if ( 0 == result )
       
   551   {
       
   552     result = pthread_mutexattr_settype( &amp; attr, PTHREAD_MUTEX_ERRORCHECK );
       
   553   }
       
   554 
       
   555   /* The following is a race against simultaneous calls to init */
       
   556   if ( 0 == result )
       
   557   {
       
   558     result = pthread_mutex_init( &amp; spin-&gt;mutex, &amp; attr );
       
   559   }
       
   560 
       
   561   if ( 0 == result )
       
   562   {
       
   563     spin-&gt;magic = spin_magic;     
       
   564   }
       
   565 
       
   566   ( void ) pthread_mutexattr_destroy( &amp; attr );
       
   567   return result;
       
   568 }
       
   569 
       
   570 /**
       
   571  Function: spinlock_destroy
       
   572  Description:
       
   573    Releases system resources allocated to a spinlock
       
   574    structure during initializion.
       
   575  Parameters:
       
   576    spin - a pointer to a previously initialized but
       
   577      not destroyed spinlock.
       
   578 **/
       
   579 int spinlock_destroy( spinlock * spin )
       
   580 {
       
   581   int result;
       
   582 
       
   583   if ( NULL == spin || spin_magic != spin-&gt;magic )
       
   584   {
       
   585     return EINVAL;
       
   586   }
       
   587 
       
   588   if ( 0 != ( result = pthread_mutex_destroy( &amp; spin-&gt;mutex ) ) )
       
   589   {
       
   590     return result;
       
   591   }
       
   592 
       
   593   ( void ) memset( &amp; spin-&gt;owner, 0, sizeof( pthread_t ) );
       
   594 
       
   595   /**
       
   596    A return of EINVAL on destroy means another thread is
       
   597    also destroying.  Ignore it.
       
   598   **/
       
   599   spin-&gt;magic = 0;
       
   600 
       
   601   return 0;
       
   602 }
       
   603 
       
   604 /**
       
   605  Function: spinlock_lock
       
   606  Description:
       
   607    Attempts to acquire exclusive access to the specified
       
   608    spinlock.  If the spinlock is already owned then begin
       
   609    spinning until ownership is obtained.
       
   610 
       
   611  Parameters:
       
   612    spin - a pointer to an initialized spinlock.
       
   613 **/
       
   614 int spinlock_lock( spinlock * spin )
       
   615 {
       
   616   pthread_t self;
       
   617   int result;
       
   618   int spin_count;
       
   619 
       
   620   if ( NULL == spin || spin_magic != spin-&gt;magic )
       
   621   {
       
   622     return EINVAL;
       
   623   }
       
   624 
       
   625   self = pthread_self( );
       
   626   if ( 0 == memcmp( &amp; spin-&gt;owner, &amp; self, sizeof( pthread_t ) ) )
       
   627   {
       
   628     return EDEADLK;
       
   629   }
       
   630 
       
   631   for ( ; 0 != ( result = pthread_mutex_trylock( &amp; spin-&gt;mutex ) ) ; )
       
   632   {
       
   633     if ( EBUSY == result )
       
   634     {
       
   635       ++ spin_count;
       
   636 
       
   637       if ( SPINLOCK_SPIN_MAX == spin_count )
       
   638       {
       
   639         ( void ) sched_yield( );
       
   640         spin_count = 0;
       
   641       }
       
   642     }
       
   643     else
       
   644     {
       
   645       /* Destroy occurred on us... */
       
   646       return EINVAL;
       
   647     }
       
   648   }
       
   649 
       
   650   ( void ) memcpy( &amp; spin-&gt;owner, &amp; self, sizeof( pthread_t ) );
       
   651   return result;
       
   652 }
       
   653 
       
   654 /**</codeblock> </section>
       
   655 <section id="GUID-777FDBF9-4B80-5B58-88F3-E78DBDB89021"><title>Command line
       
   656 shell</title> <p>Symbian platform phones do not have a command line shell
       
   657 as standard. P.I.P.S. does however support the <xref href="GUID-C0C1D22B-298F-3E8D-A1E9-6F5EFA81F9E8.dita"><apiname>stdin()</apiname></xref>, <xref href="GUID-85797574-E2A2-3C0C-9670-C178078DE199.dita"><apiname>stdout()</apiname></xref> and <xref href="GUID-4FF97B50-2C1E-37EC-888B-FB8D3F14B5B8.dita"><apiname>stderr()</apiname></xref> standard
       
   658 streams, enabling parent processes to redirect a child's standard streams
       
   659 for the exchange of data. Without explicitly redirecting the standard streams,
       
   660 the default is for each to be redirected to the <filepath>/dev/null</filepath> directory.
       
   661 The P.I.P.S. <xref href="GUID-3D9040E5-F6FB-3DEA-9800-A55F0CEE7B08.dita"><apiname>system()</apiname></xref> function does not create a shell
       
   662 for a new program as in most POSIX implementations, however, it will start
       
   663 a program and return the program's exit value. </p> </section>
       
   664 <section id="GUID-98FE0A61-A9F6-5216-A01F-A213F33D3173"><title>User interfaces</title> <p>Most
       
   665 POSIX based systems interact with a windowing system such as X Windows and
       
   666 libraries such as GTK. P.I.P.S., however, does not have its own UI libraries,
       
   667 so any P.I.P.S. based applications that require UI functionality must rely
       
   668 on the UI from the device manufacturer. As a consequence, for any UI program
       
   669 that uses P.I.P.S., there must be an interaction between Symbian platform
       
   670 native C++ and P.I.P.S. C code. </p> </section>
       
   671 <section id="GUID-3CA8FF29-79B4-5D43-8A23-EDB136BF7A8F"><title>One Definition
       
   672 Rule - warning</title> <p>Standard C++ states that the <keyword>One Definition
       
   673 Rule</keyword> (ODR) must be maintained within a program. </p> <p>Symbian
       
   674 platform can neither check (without significant modifications) that the ODR
       
   675 is violated nor use the technique called symbol pre-emption to ensure that
       
   676 the ODR is enforced. </p> <p>Therefore, you must take care and must not assume
       
   677 that there is only one copy of the symbol (that is, all instances of the same
       
   678 symbol will have the same address) across all DLLs within a program. </p> </section>
       
   679 </conbody></concept>