[PATCH 3/7] toolsoftrade: Employ new scheme for snippets of lock.c

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



>From 4bf3961a5c8501a9983a196119038b74cff7a18d Mon Sep 17 00:00:00 2001
From: Akira Yokosawa <akiyks@xxxxxxxxx>
Date: Sun, 14 Oct 2018 16:23:34 +0900
Subject: [PATCH 3/7] toolsoftrade: Employ new scheme for snippets of lock.c

NOTE: Several "if" statements, which are too wide for 2c layout,
are divided into a statement to get error code and a simple "if"
statement.

Signed-off-by: Akira Yokosawa <akiyks@xxxxxxxxx>
---
 CodeSamples/toolsoftrade/lock.c |  76 +++++++++--------
 toolsoftrade/toolsoftrade.tex   | 175 +++++++++++-----------------------------
 2 files changed, 89 insertions(+), 162 deletions(-)

diff --git a/CodeSamples/toolsoftrade/lock.c b/CodeSamples/toolsoftrade/lock.c
index 6bb3c23..7b56c0f 100644
--- a/CodeSamples/toolsoftrade/lock.c
+++ b/CodeSamples/toolsoftrade/lock.c
@@ -26,62 +26,64 @@
 #include <errno.h>
 #include "../api.h"
 
-pthread_mutex_t lock_a = PTHREAD_MUTEX_INITIALIZER;
-pthread_mutex_t lock_b = PTHREAD_MUTEX_INITIALIZER;
+//\begin{snippet}[labelbase=ln:toolsoftrade:lock:reader_writer,commandchars=\$\[\]]
+pthread_mutex_t lock_a = PTHREAD_MUTEX_INITIALIZER;	//\lnlbl{lock_a}
+pthread_mutex_t lock_b = PTHREAD_MUTEX_INITIALIZER;	//\lnlbl{lock_b}
 
-int x = 0;
+int x = 0;						//\lnlbl{x}
 
-void *lock_reader(void *arg)
+void *lock_reader(void *arg)				//\lnlbl{reader:b}
 {
 	int en;
 	int i;
 	int newx = -1;
 	int oldx = -1;
-	pthread_mutex_t *pmlp = (pthread_mutex_t *)arg;
+	pthread_mutex_t *pmlp = (pthread_mutex_t *)arg;	//\lnlbl{reader:cast}
 
-	if ((en = pthread_mutex_lock(pmlp)) != 0) {
+	if ((en = pthread_mutex_lock(pmlp)) != 0) {	//\lnlbl{reader:acq:b}
 		fprintf(stderr, "lock_reader:pthread_mutex_lock: %s\n",
 			strerror(en));
 		exit(EXIT_FAILURE);
-	}
-	for (i = 0; i < 100; i++) {
-		newx = READ_ONCE(x);
+	}						//\lnlbl{reader:acq:e}
+	for (i = 0; i < 100; i++) {			//\lnlbl{reader:loop:b}
+		newx = READ_ONCE(x);			//\lnlbl{reader:read_x}
 		if (newx != oldx) {
 			printf("lock_reader(): x = %d\n", newx);
 		}
 		oldx = newx;
-		poll(NULL, 0, 1);
-	}
-	if ((en = pthread_mutex_unlock(pmlp)) != 0) {
+		poll(NULL, 0, 1);			//\lnlbl{reader:sleep}
+	}						//\lnlbl{reader:loop:e}
+	if ((en = pthread_mutex_unlock(pmlp)) != 0) {	//\lnlbl{reader:rel:b}
 		fprintf(stderr, "lock_reader:pthread_mutex_lock: %s\n",
 			strerror(en));
 		exit(EXIT_FAILURE);
-	}
-	return NULL;
-}
+	}						//\lnlbl{reader:rel:e}
+	return NULL;					//\lnlbl{reader:return}
+}							//\lnlbl{reader:e}
 
-void *lock_writer(void *arg)
+void *lock_writer(void *arg)				//\lnlbl{writer:b}
 {
 	int en;
 	int i;
-	pthread_mutex_t *pmlp = (pthread_mutex_t *)arg;
+	pthread_mutex_t *pmlp = (pthread_mutex_t *)arg;	//\lnlbl{writer:cast}
 
-	if ((en = pthread_mutex_lock(pmlp)) != 0) {
+	if ((en = pthread_mutex_lock(pmlp)) != 0) {	//\lnlbl{writer:acq:b}
 		fprintf(stderr, "lock_writer:pthread_mutex_lock: %s\n",
 			strerror(en));
 		exit(EXIT_FAILURE);
-	}
-	for (i = 0; i < 3; i++) {
-		WRITE_ONCE(x, READ_ONCE(x) + 1);
+	}						//\lnlbl{writer:acq:e}
+	for (i = 0; i < 3; i++) {			//\lnlbl{writer:loop:b}
+		WRITE_ONCE(x, READ_ONCE(x) + 1);	//\lnlbl{writer:inc}
 		poll(NULL, 0, 5);
-	}
-	if ((en = pthread_mutex_unlock(pmlp)) != 0) {
+	}						//\lnlbl{writer:loop:e}
+	if ((en = pthread_mutex_unlock(pmlp)) != 0) {	//\lnlbl{writer:rel:b}
 		fprintf(stderr, "lock_writer:pthread_mutex_lock: %s\n",
 			strerror(en));
 		exit(EXIT_FAILURE);
-	}
+	}						//\lnlbl{writer:rel:e}
 	return NULL;
-}
+}							//\lnlbl{writer:e}
+//\end{snippet}
 
 int main(int argc, char *argv[])
 {
@@ -90,31 +92,38 @@ int main(int argc, char *argv[])
 	pthread_t tid2;
 	void *vp;
 
+//\begin{snippet}[labelbase=ln:toolsoftrade:lock:same_lock,commandchars=\$\[\]]
 	printf("Creating two threads using same lock:\n");
-	if ((en = pthread_create(&tid1, NULL, lock_reader, &lock_a)) != 0) {
+	en = pthread_create(&tid1, NULL, lock_reader, &lock_a);	//\lnlbl{cr:reader:b}
+	if (en != 0) {
 		fprintf(stderr, "pthread_create: %s\n", strerror(en));
 		exit(EXIT_FAILURE);
-	}
-	if ((en = pthread_create(&tid2, NULL, lock_writer, &lock_a)) != 0) {
+	}							//\lnlbl{cr:reader:e}
+	en = pthread_create(&tid2, NULL, lock_writer, &lock_a); //\lnlbl{cr:writer:b}
+	if (en != 0) {
 		fprintf(stderr, "pthread_create: %s\n", strerror(en));
 		exit(EXIT_FAILURE);
-	}
-	if ((en = pthread_join(tid1, &vp)) != 0) {
+	}							//\lnlbl{cr:writer:e}
+	if ((en = pthread_join(tid1, &vp)) != 0) {	//\lnlbl{wait:b}
 		fprintf(stderr, "pthread_join: %s\n", strerror(en));
 		exit(EXIT_FAILURE);
 	}
 	if ((en = pthread_join(tid2, &vp)) != 0) {
 		fprintf(stderr, "pthread_join: %s\n", strerror(en));
 		exit(EXIT_FAILURE);
-	}
+	}						//\lnlbl{wait:e}
+//\end{snippet}
 
+//\begin{snippet}[labelbase=ln:toolsoftrade:lock:diff_lock,commandchars=\$\[\]]
 	printf("Creating two threads w/different locks:\n");
 	x = 0;
-	if ((en = pthread_create(&tid1, NULL, lock_reader, &lock_a)) != 0) {
+	en = pthread_create(&tid1, NULL, lock_reader, &lock_a);
+	if (en != 0) {
 		fprintf(stderr, "pthread_create: %s\n", strerror(en));
 		exit(EXIT_FAILURE);
 	}
-	if ((en = pthread_create(&tid2, NULL, lock_writer, &lock_b)) != 0) {
+	en = pthread_create(&tid2, NULL, lock_writer, &lock_b);
+	if (en != 0) {
 		fprintf(stderr, "pthread_create: %s\n", strerror(en));
 		exit(EXIT_FAILURE);
 	}
@@ -126,6 +135,7 @@ int main(int argc, char *argv[])
 		fprintf(stderr, "pthread_join: %s\n", strerror(en));
 		exit(EXIT_FAILURE);
 	}
+//\end{snippet}
 
 	return EXIT_SUCCESS;
 }
diff --git a/toolsoftrade/toolsoftrade.tex b/toolsoftrade/toolsoftrade.tex
index 601829c..e699b6e 100644
--- a/toolsoftrade/toolsoftrade.tex
+++ b/toolsoftrade/toolsoftrade.tex
@@ -460,82 +460,32 @@ lock~\cite{Hoare74}.
 } \QuickQuizEnd
 
 \begin{listing}[tbp]
-{ \scriptsize
-\begin{verbbox}
-  1 pthread_mutex_t lock_a = PTHREAD_MUTEX_INITIALIZER;
-  2 pthread_mutex_t lock_b = PTHREAD_MUTEX_INITIALIZER;
-  3 int x = 0;
-  4 
-  5 void *lock_reader(void *arg)
-  6 {
-  7   int i;
-  8   int newx = -1;
-  9   int oldx = -1;
- 10   pthread_mutex_t *pmlp = (pthread_mutex_t *)arg;
- 11 
- 12   if (pthread_mutex_lock(pmlp) != 0) {
- 13     perror("lock_reader:pthread_mutex_lock");
- 14     exit(EXIT_FAILURE);
- 15   }
- 16   for (i = 0; i < 100; i++) {
- 17     newx = READ_ONCE(x);
- 18     if (newx != oldx) {
- 19       printf("lock_reader(): x = %d\n", newx);
- 20     }
- 21     oldx = newx;
- 22     poll(NULL, 0, 1);
- 23   }
- 24   if (pthread_mutex_unlock(pmlp) != 0) {
- 25     perror("lock_reader:pthread_mutex_unlock");
- 26     exit(EXIT_FAILURE);
- 27   }
- 28   return NULL;
- 29 }
- 30 
- 31 void *lock_writer(void *arg)
- 32 {
- 33   int i;
- 34   pthread_mutex_t *pmlp = (pthread_mutex_t *)arg;
- 35 
- 36   if (pthread_mutex_lock(pmlp) != 0) {
- 37     perror("lock_writer:pthread_mutex_lock");
- 38     exit(EXIT_FAILURE);
- 39   }
- 40   for (i = 0; i < 3; i++) {
- 41     WRITE_ONCE(x, READ_ONCE(x) + 1);
- 42     poll(NULL, 0, 5);
- 43   }
- 44   if (pthread_mutex_unlock(pmlp) != 0) {
- 45     perror("lock_writer:pthread_mutex_unlock");
- 46     exit(EXIT_FAILURE);
- 47   }
- 48   return NULL;
- 49 }
-\end{verbbox}
-}
-\centering
-\theverbbox
+\input{CodeSamples/toolsoftrade/lock@reader_writer.fcv}
 \caption{Demonstration of Exclusive Locks}
 \label{lst:toolsoftrade:Demonstration of Exclusive Locks}
 \end{listing}
 
+\begin{lineref}[ln:toolsoftrade:lock:reader_writer]
 This exclusive-locking property is demonstrated using the code shown in
 Listing~\ref{lst:toolsoftrade:Demonstration of Exclusive Locks}
 (\path{lock.c}).
-Line~1 defines and initializes a POSIX lock named \co{lock_a}, while
-line~2 similarly defines and initializes a lock named \co{lock_b}.
-Line~3 defines and initializes a shared variable~\co{x}.
+Line~\lnref{lock_a} defines and initializes a POSIX lock named \co{lock_a}, while
+line~\lnref{lock_b} similarly defines and initializes a lock named \co{lock_b}.
+Line~\lnref{x} defines and initializes a shared variable~\co{x}.
+\end{lineref}
 
-Lines~5-28 defines a function \co{lock_reader()} which repeatedly
+\begin{lineref}[ln:toolsoftrade:lock:reader_writer:reader]
+Lines~\lnref{b}-\lnref{e} defines a function \co{lock_reader()} which repeatedly
 reads the shared variable \co{x} while holding
 the lock specified by \co{arg}.
-Line~10 casts \co{arg} to a pointer to a \co{pthread_mutex_t}, as
+Line~\lnref{cast} casts \co{arg} to a pointer to a \co{pthread_mutex_t}, as
 required by the \co{pthread_mutex_lock()} and \co{pthread_mutex_unlock()}
 primitives.
+\end{lineref}
 
 \QuickQuiz{}
 	Why not simply make the argument to \co{lock_reader()}
-	on line~5 of
+	on line~\ref{ln:toolsoftrade:lock:reader_writer:reader:b} of
 	Listing~\ref{lst:toolsoftrade:Demonstration of Exclusive Locks}
 	be a pointer to a \co{pthread_mutex_t}?
 \QuickQuizAnswer{
@@ -547,9 +497,12 @@ primitives.
 } \QuickQuizEnd
 
 \QuickQuiz{}
-	What is the \co{READ_ONCE()} on lines~17 and~41 and the
-	\co{WRITE_ONCE()} on line~41 of
+	\begin{lineref}[ln:toolsoftrade:lock:reader_writer]
+	What is the \co{READ_ONCE()} on
+        lines~\lnref{reader:read_x} and~\lnref{writer:inc} and the
+	\co{WRITE_ONCE()} on line~\lnref{writer:inc} of
 	Listing~\ref{lst:toolsoftrade:Demonstration of Exclusive Locks}?
+	\end{lineref}
 \QuickQuizAnswer{
 	These macros constrain the compiler so as to prevent it from
 	carrying out optimizations that would be problematic for concurrently
@@ -569,16 +522,21 @@ primitives.
 	Chapter~\ref{chp:Advanced Synchronization: Memory Ordering}.
 } \QuickQuizEnd
 
-Lines~12-15 acquire the specified \co{pthread_mutex_t}, checking
+\begin{lineref}[ln:toolsoftrade:lock:reader_writer:reader]
+Lines~\lnref{acq:b}-\lnref{acq:e} acquire the specified
+\co{pthread_mutex_t}, checking
 for errors and exiting the program if any occur.
-Lines~16-23 repeatedly check the value of \co{x}, printing the new value
+Lines~\lnref{loop:b}-\lnref{loop:e} repeatedly check the value of \co{x},
+printing the new value
 each time that it changes.
-Line~22 sleeps for one millisecond, which allows this demonstration
+Line~\lnref{sleep} sleeps for one millisecond, which allows this demonstration
 to run nicely on a uniprocessor machine.
-Lines~24-27 release the \co{pthread_mutex_t}, again checking for
+Lines~\lnref{rel:b}-\lnref{rel:e} release the \co{pthread_mutex_t},
+again checking for
 errors and exiting the program if any occur.
-Finally, line~28 returns \co{NULL}, again to match the function type
+Finally, line~\lnref{return} returns \co{NULL}, again to match the function type
 required by \co{pthread_create()}.
+\end{lineref}
 
 \QuickQuiz{}
 	Writing four lines of code for each acquisition and release
@@ -593,55 +551,39 @@ required by \co{pthread_create()}.
 	\co{spin_lock()} and \co{spin_unlock()} APIs.
 } \QuickQuizEnd
 
-Lines~31-49 of
+\begin{lineref}[ln:toolsoftrade:lock:reader_writer:writer]
+Lines~\lnref{b}-\lnref{e} of
 Listing~\ref{lst:toolsoftrade:Demonstration of Exclusive Locks}
 shows \co{lock_writer()}, which
 periodically update the shared variable \co{x} while holding the
 specified \co{pthread_mutex_t}.
-As with \co{lock_reader()}, line~34 casts \co{arg} to a pointer
-to \co{pthread_mutex_t}, lines~36-39 acquires the specified lock,
-and lines~44-47 releases it.
-While holding the lock, lines~40-43 increment the shared variable \co{x},
+As with \co{lock_reader()}, line~\lnref{cast} casts \co{arg} to a pointer
+to \co{pthread_mutex_t},
+lines~\lnref{acq:b}-\lnref{acq:e} acquires the specified lock,
+and lines~\lnref{rel:b}-\lnref{rel:e} releases it.
+While holding the lock, lines~\lnref{loop:b}-\lnref{loop:e}
+increment the shared variable \co{x},
 sleeping for five milliseconds between each increment.
-Finally, lines~44-47 release the lock.
+Finally, lines~\lnref{rel:b}-\lnref{rel:e} release the lock.
+\end{lineref}
 
 \begin{listing}[tbp]
-{ \scriptsize
-\begin{verbbox}
-  1   printf("Creating two threads using same lock:\n");
-  2   if (pthread_create(&tid1, NULL,
-  3                      lock_reader, &lock_a) != 0) {
-  4     perror("pthread_create");
-  5     exit(EXIT_FAILURE);
-  6   }
-  7   if (pthread_create(&tid2, NULL,
-  8                      lock_writer, &lock_a) != 0) {
-  9     perror("pthread_create");
- 10     exit(EXIT_FAILURE);
- 11   }
- 12   if (pthread_join(tid1, &vp) != 0) {
- 13     perror("pthread_join");
- 14     exit(EXIT_FAILURE);
- 15   }
- 16   if (pthread_join(tid2, &vp) != 0) {
- 17     perror("pthread_join");
- 18     exit(EXIT_FAILURE);
- 19   }
-\end{verbbox}
-}
-\centering
-\theverbbox
+\input{CodeSamples/toolsoftrade/lock@same_lock.fcv}
 \caption{Demonstration of Same Exclusive Lock}
 \label{lst:toolsoftrade:Demonstration of Same Exclusive Lock}
 \end{listing}
 
+\begin{lineref}[ln:toolsoftrade:lock:same_lock]
 Listing~\ref{lst:toolsoftrade:Demonstration of Same Exclusive Lock}
 shows a code fragment that runs \co{lock_reader()} and
 \co{lock_writer()} as threads using the same lock, namely, \co{lock_a}.
-Lines~2-6 create a thread running \co{lock_reader()}, and then
-Lines~7-11 create a thread running \co{lock_writer()}.
-Lines~12-19 wait for both threads to complete.
+Lines~\lnref{cr:reader:b}-\lnref{cr:reader:e} create a thread
+running \co{lock_reader()}, and then
+Lines~\lnref{cr:writer:b}-\lnref{cr:writer:e} create a thread
+running \co{lock_writer()}.
+Lines~\lnref{wait:b}-\lnref{wait:e} wait for both threads to complete.
 The output of this code fragment is as follows:
+\end{lineref}
 
 \begin{VerbatimU}
 Creating two threads using same lock:
@@ -672,32 +614,7 @@ by \co{lock_writer()} while holding the lock.
 } \QuickQuizEnd
 
 \begin{listing}[tbp]
-{ \scriptsize
-\begin{verbbox}
-  1   printf("Creating two threads w/different locks:\n");
-  2   x = 0;
-  3   if (pthread_create(&tid1, NULL,
-  4                      lock_reader, &lock_a) != 0) {
-  5     perror("pthread_create");
-  6     exit(EXIT_FAILURE);
-  7   }
-  8   if (pthread_create(&tid2, NULL,
-  9                      lock_writer, &lock_b) != 0) {
- 10     perror("pthread_create");
- 11     exit(EXIT_FAILURE);
- 12   }
- 13   if (pthread_join(tid1, &vp) != 0) {
- 14     perror("pthread_join");
- 15     exit(EXIT_FAILURE);
- 16   }
- 17   if (pthread_join(tid2, &vp) != 0) {
- 18     perror("pthread_join");
- 19     exit(EXIT_FAILURE);
- 20   }
-\end{verbbox}
-}
-\centering
-\theverbbox
+\input{CodeSamples/toolsoftrade/lock@diff_lock.fcv}
 \caption{Demonstration of Different Exclusive Locks}
 \label{lst:toolsoftrade:Demonstration of Different Exclusive Locks}
 \end{listing}
@@ -761,7 +678,7 @@ values of \co{x} stored by \co{lock_writer()}.
 	so why does it need to be initialized in
 	Listing~\ref{lst:toolsoftrade:Demonstration of Different Exclusive Locks}?
 \QuickQuizAnswer{
-	See line~3 of
+	See line~\ref{ln:toolsoftrade:lock:reader_writer:x} of
 	Listing~\ref{lst:toolsoftrade:Demonstration of Exclusive Locks}.
 	Because the code in
 	Listing~\ref{lst:toolsoftrade:Demonstration of Same Exclusive Lock}
-- 
2.7.4





[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [Linux NFS]     [Linux NILFS]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux