Multithreading & Multitasking

Hi,
I've decided to post in this category because all the others are too specific. "Fundamental approaches to software development for OS X" sounds about right.
I'd like to know exactly how Mac OS X is supposed to be considered an OS that does true multitasking.
Have you ever seen one subprocess of an app take on its course while another subprocess was hung? Ever seen a Finder window behave while another window was stuck in a lost AppleShare mount? Ever seen a Safari window be usable while another Safari window was stuck on a php script with infinite output or a crashing Flash app?
My point is: Why can't apps keep running their subprocesses independently from eachother if one of them is stuck, e.g. waiting for an I/O task to finish?
How is this considered true multitasking or even multithreading?
Should I expect Apple to ever think about this for a next OS release? Really, one could say it is prehistoric for entire apps to hang if one of their windows or threads hang.
Just curious to see if I'm alone in this.

Hi Joris
Technically, Mac OS X is based on Unix. Unix is a true multitasking operating system and any application can spawn subtasks.
However, providing a multitasking facility is one thing, but designing a program to use it is another. In general, applications which use multitasking are more difficult to design and debug so a software designer may consider it more cost effective to ignore multitasking. If you don't like the behaviour of a particular app, then you should discuss it in the appropriate forum for that application and/or raise a bug report with Apple.
If you want a system with no bugs in it then Apple (or Microsoft) can build you one - but it will cost 20 million dollars for a single user licence and it will be available in 10 years time. Or you can settle for an affordable OS X with the occasional hang up!
As with all commercial products, it all boils down to cost.
Bob

Similar Messages

  • Difference and advantages of java and c++

    whats the best advantage of java over c++
    also the basic difference between java and c++
    what the difference between multithreading, multitasking and multiprocessing
    what if there r 2 main methods in 1 java program with different signature
    difference between method overloading and method overriding

    whats the best advantage of java over c++Java is simpler.
    also the basic difference between java and c++Java is easyly portable. It has a GUI (Swing), multi-tasking and garbage collection as standard.
    what the difference between multithreading,
    multitasking and multiprocessingMultithreading is mostly used at the language level to mean many threads of execution. Multitasking is mostly used at the OS level to mean many processes (program units) runing at the same time. That should cover multiprocessing too but here processing can also be used in a broader sense at the application level to mean any "process" you can think of.
    what if there r 2 main methods in 1 java program with
    different signatureYou'll have to specify which one you want executed I guess. Try it out!
    difference between method overloading and method
    overridingOverloading is a convinience facility. It allows you to let methods in a class have the same name as long as their signatures differ.
    Overriding is when a method defined in a superclass is replaced with a new one with the exact same signature in a subclass.

  • Multitasking & multithreading

    I'm confused with multi threading...I feel it sounds like the same meaning of mutlti tasking. Can anyone please explain me how multi threading varies from multi tasking?
    And what is the importance of using multithreading in an application?

    Multi tasking referes to running more than one program in an operating system. These programs each have their own data space that is not shared. Multithreading referes to a program that has more than one thread of execution and they all reside in the same dataspace and the threads can share data without the need of an external OS constructs. (Windows provides DDE(Dynamc Data Exchange) and OLE(Object Linking and Embeding) to allow programs to share data).
    That is the main difference between multithreading and multitasking.

  • More than one VI at a time (i.e. multitasking)

    Hello.
    I currently work in a lab where we use LabVIEW to control an multifunction instrument. We use the sofware both for data acquisition (through Ni-DAQ) and for physical control of things like stages, and frequency generators (e.g. through GPIB). There are a few programs that do very simple things (like move a stage with a joystick, or turn a laser on and off) that I would like to run continuously in the background while I run other more specialized software (like a data acquisiton routine). However, when I run more than one VI at the same time I run into very bad timing problems. Some of my programs require this kind of multitasking and I have implemented it using a sort of Master loop (similiar to the Master/S
    lave paradigm discussed on the NI website).
    If I were to purchase the compiler and build executables out of some of the VIs, would I be able to run these in the background while LabVIEW runs other VIs without running into timing issues?
    Also, if I build executables from some of the VIs would these VIs be able to access global variables that LabVIEW is using (I assume the answer is no, but I figured I'd ask).
    Thanks,
    Josh
    [email protected]
    =====================
    Joshua Shaevitz
    Department of Physics
    Stanford University
    Stanford, CA 94305

    First, do you know where your timing problems are coming from? Are some of those background tasks very processor intensive, or is the problem that you're sharing subVIs that aren't reentrant (and hence may be "blocking" each other)? Have you tried multithreading the application yet (running the motion control in one thread and the laser control in another, for instance)?
    Splitting your tasks between multiple executables might help, but it will almost certainly increase the overhead of each background task, and you will not have common access to global variables. You could, however, work around that by instituting a common data repository as one of your background tasks (presumably accessed through a messaging interface).
    In fact, I would probably suggest
    this as a method of performance optimizing your application anyway -- if you are using globals extensively for parallel operation, they might be part of the blocking problem.

  • Solaris vs Linux For Multithreaded Application

    Hi all,
    I am having a Multithreaded Java application which is used to monitor devices in a network (NMS). After collecting the data from the devices, this will update the data in the database. (Usualy there will be lot of device around 25000) . There will be lot of database updation. I am planning to run this application in a server.
    But now I am confused in selecting which platform (which os) I have to use. There are two options for me. Either to use Linux or Solaris.
    Can anyone help me in selecting the platform. Since my application is multithreaded , please tell me which of these OS will give the best performance
    Thanks in advance

    There's no way to tell which one performs better without testing it. Both have reasonably mature and stable multitasking and multi threading. Why don't you write the application and try it on both platforms?

  • Multitasking on iPod Touch 4G, running iOS 6.1.2, nearly impossible. Opened,  background apps do not seem to stay in memory and must "reload" every time I switch back to them. Also, intense battery drain (imo).

    Let's say I'm playing Words with Friends, and also Angry Birds. I may want to go back and forth between the two. When I do so, the app that was in the background needs to reload again. There is no quick access or ability to quickly resume where I left off. And the reloading means that the app restarts from its opening screens...so if I was working on a level, I have to start all over again. And quite often, a game like Angry Birds will lag greatly when I first open it...moving almost in slow-motion.
    I don't know if this is typical behavior when playing multiple games, or if I have an issue with my device. I've rebooted and even reset and restored, all to no avail.
    There doesn't appear to be as much of an issue if I'm playing one game but also have the music player open, or Safari, Notes, Reminders, etc. Those will resume just fine, though there may be some lag when opening/re-opening them.
    So I guess the problem seems to lie within 3rd party apps, and not the apps that are part of the iPod/iOS.
    The other problem is battery drain. I do all of my music listening via Bluetooth, so I expect that to have a greater impact than if I were using plugged in headphones, and I have location services turned on. But I have most notifications turned off, all email accounts set to manual and not push, screen brightness turned down and auto brightness turned on, "ask to join networks" turned off, auto-lock is set to 2 minutes but I almost always turn off the screen immediately after setting up my music listening (since I do so at work), volume limit turned on, EQ turned off, sound check turned off,
    With these settings, my battery can drain 20% or more within 10-15 minutes of game play. And these are not what I would consider memory intensive games--just Words and Angry Birds.
    I've installed (and recently uninstalled) a couple of battery meters from the Apple Store as well--freebies. Carat, Battery Doctor, Battery HD, Battery Magic.
    Carat and Battery Doctor seemed to offer the most pertinent and accurate information so the others were uninstalled long ago.
    The Accelerate tab in Battery Doctor show the amount of memory in use, and the amount of available memory. The vast majority of the time, the memory in use is approximately 94%. I will occasionally choose to "accelerate" which supposedly frees up memory, but this "bump" lasts only a brief time and I'm not sure it's a great idea.
    Even with absolutely nothing open or running, my used memory is generally still above 80%.
    Carat, if anyone is familiar with it, shows a J-Score. My J-Score is 17, which means that my performance (according to Carat, anyway) is better than only 17% of the users who have Carat installed. In other words, 83% of people are getting better performance from their devices. It also has "battery hog" and "battery bug" sections. It doesn't detect any hogs or bugs.
    I use my iPod Touch in rather limited ways. A typical day consists of approximately 5 hours of music listening via Bluetooth and 30 minutes to 1 hour of playing the aforementioned games. The occasional note and reminder, perhaps a brief check-in with the weather, and that's about it. And wifi is in use only when at home (there is no hotspot at work). Still, I need to charge it every day. I'd be keen to do more with the iPod if I could count on it to last more than a day.
    I've read up on multiple forums and blogs for tips on prolonging a battery charge, and believe I've taken everything into account, and applied whatever I could. I've even reset the network settings and try to discharge the battery completely once a month (for supposed battery calibration).
    I'm really hoping people can offer some suggestions or comments on whether this is typical behavior or if my battery is going, or even offer some additional tips.
    With iOS 7 on the horizon, I'm hoping the upgrade will offer some resolutions (I've read there is better multitasking), but considering how weakly my device performs at this point, I'm not entirely convinced that an iOS upgrade will actually make any improvements.
    Thanks a lot for reading.

    No, the app does not have to completely restart. It gets shifted in its open state into storage. Similar to how a computer uses the hard disk when it has insufficient memory.
    What complicates things is that sometimes memory does not get returned for reuse when you close an app. Thus yo should periodically double click the Home button and "delete" unnecessary apps from the multitasking dock and power off and then back on the iPod.

  • Video transmission with multithreading. I am having a problem?

    I am doing an application for sending video streams to multiple clients at the same time. So am using multithreading. I have the following codes to do the transmission. When I am using it with one thread only it is working fine. But when I use it with more threads for multiple transmissions I am have an error saying �Unable to realize com.sun.media.ProcessEngine�. Can anyone help me plz.
    import java.awt.*;
    import javax.media.*;
    import javax.media.protocol.*;
    import javax.media.protocol.DataSource;
    import javax.media.format.*;
    import javax.media.control.TrackControl;
    import javax.media.control.QualityControl;
    import java.io.*;
    import java.lang.Thread;
    public class VideoTransmitThread extends Thread{
    // Input MediaLocator
    // Can be a file or http or capture source
    private MediaLocator locator;
    private String ipAddress;
    private String port;
    private Processor processor = null;
    private DataSink rtptransmitter = null;
    private DataSource dataOutput = null;
    public VideoTransmitThread(MediaLocator locator,
                   String ipAddress,
                   String port) {
         this.locator = locator;
         this.ipAddress = ipAddress;
         this.port = port;
    * Starts the transmission. Returns null if transmission started ok.
    * Otherwise it returns a string with the reason why the setup failed.
    //run method for the thread
    public void run( ) {
         String result;
         // Create a processor for the specified media locator
         // and program it to output JPEG/RTP
         result =createProcessor();
         if (result != null)
         System.out.println("error: "+result);
         // Create an RTP session to transmit the output of the
         // processor to the specified IP address and port no.
         result =createTransmitter();
         if (result != null) {
         processor.close();
         processor = null;
         //return result;
         System.out.println("error: "+result);
         System.exit(0);
         try {
         Thread.sleep(1000); // 100 msec
         } catch (InterruptedException e) {
         return;
         // Start the transmission
         processor.start();
    * Stops the transmission if already started
    public void stop1() {
         synchronized (this) {
         if (processor != null) {
              processor.stop();
              processor.close();
              processor = null;
              rtptransmitter.close();
              rtptransmitter = null;
    private String createProcessor() {
         if (locator == null)
         return "Locator is null";
         DataSource ds;
         DataSource clone;
         try {
         ds = Manager.createDataSource(locator);
         } catch (Exception e) {
         return "Couldn't create DataSource";
         // Try to create a processor to handle the input media locator
         try {
         processor = Manager.createProcessor(ds);
         } catch (NoProcessorException npe) {
         return "Couldn't create processor";
         } catch (IOException ioe) {
         return "IOException creating processor";
         // Wait for it to configure
         boolean result = waitForState(processor, Processor.Configured);
         if (result == false)
         return "Couldn't configure processor";
         // Get the tracks from the processor
         TrackControl [] tracks = processor.getTrackControls();
         // Do we have atleast one track?
         if (tracks == null || tracks.length < 1)
         return "Couldn't find tracks in processor";
         boolean programmed = false;
         // Search through the tracks for a video track
         for (int i = 0; i < tracks.length; i++) {
         Format format = tracks.getFormat();
         if ( tracks[i].isEnabled() &&
              format instanceof VideoFormat &&
              !programmed) {
              // Found a video track. Try to program it to output JPEG/RTP
              // Make sure the sizes are multiple of 8's.
              Dimension size = ((VideoFormat)format).getSize();
              float frameRate = ((VideoFormat)format).getFrameRate();
              int w = (size.width % 8 == 0 ? size.width :
                        (int)(size.width / 8) * 8);
              int h = (size.height % 8 == 0 ? size.height :
                        (int)(size.height / 8) * 8);
              VideoFormat jpegFormat = new VideoFormat(VideoFormat.JPEG_RTP,
                                       new Dimension(w, h),
                                       Format.NOT_SPECIFIED,
                                       Format.byteArray,
                                       frameRate);
              tracks[i].setFormat(jpegFormat);
              System.err.println("Video transmitted as:");
              System.err.println(" " + jpegFormat);
              // Assume succesful
              programmed = true;
         } else
              tracks[i].setEnabled(false);
         if (!programmed)
         return "Couldn't find video track";
         // Set the output content descriptor to RAW_RTP
         ContentDescriptor cd = new ContentDescriptor(ContentDescriptor.RAW_RTP);
         processor.setContentDescriptor(cd);
         // Realize the processor. This will internally create a flow
         // graph and attempt to create an output datasource for JPEG/RTP
         // video frames.
         result = waitForState(processor, Controller.Realized);
         if (result == false)
         return "Couldn't realize processor";
         // Set the JPEG quality to .5.
         setJPEGQuality(processor, 0.5f);
         // Get the output data source of the processor
         dataOutput = processor.getDataOutput();
         return null;
    // Creates an RTP transmit data sink. This is the easiest way to create
    // an RTP transmitter. The other way is to use the RTPSessionManager API.
    // Using an RTP session manager gives you more control if you wish to
    // fine tune your transmission and set other parameters.
    private String createTransmitter() {
         // Create a media locator for the RTP data sink.
         // For example:
         // rtp://129.130.131.132:42050/video
         String rtpURL = "rtp://" + ipAddress + ":" + port + "/video";
         MediaLocator outputLocator = new MediaLocator(rtpURL);
         // Create a data sink, open it and start transmission. It will wait
         // for the processor to start sending data. So we need to start the
         // output data source of the processor. We also need to start the
         // processor itself, which is done after this method returns.
         try {
         rtptransmitter = Manager.createDataSink(dataOutput, outputLocator);
         rtptransmitter.open();
         rtptransmitter.start();
         dataOutput.start();
         } catch (MediaException me) {
         return "Couldn't create RTP data sink";
         } catch (IOException ioe) {
         return "Couldn't create RTP data sink";
         return null;
    * Setting the encoding quality to the specified value on the JPEG encoder.
    * 0.5 is a good default.
    void setJPEGQuality(Player p, float val) {
         Control cs[] = p.getControls();
         QualityControl qc = null;
         VideoFormat jpegFmt = new VideoFormat(VideoFormat.JPEG);
         // Loop through the controls to find the Quality control for
         // the JPEG encoder.
         for (int i = 0; i < cs.length; i++) {
         if (cs[i] instanceof QualityControl &&
              cs[i] instanceof Owned) {
              Object owner = ((Owned)cs[i]).getOwner();
              // Check to see if the owner is a Codec.
              // Then check for the output format.
              if (owner instanceof Codec) {
              Format fmts[] = ((Codec)owner).getSupportedOutputFormats(null);
              for (int j = 0; j < fmts.length; j++) {
                   if (fmts[j].matches(jpegFmt)) {
                   qc = (QualityControl)cs[i];
                   qc.setQuality(val);
                   System.err.println("- Setting quality to " +
                             val + " on " + qc);
                   break;
              if (qc != null)
              break;
    * Convenience methods to handle processor's state changes.
    private Integer stateLock = new Integer(0);
    private boolean failed = false;
    Integer getStateLock() {
         return stateLock;
    void setFailed() {
         failed = true;
    private synchronized boolean waitForState(Processor p, int state) {
         p.addControllerListener(new StateListener());
         failed = false;
         // Call the required method on the processor
         if (state == Processor.Configured) {
         p.configure();
         } else if (state == Processor.Realized) {
         p.realize();
         // Wait until we get an event that confirms the
         // success of the method, or a failure event.
         // See StateListener inner class
         while (p.getState() < state && !failed) {
         synchronized (getStateLock()) {
              try {
              getStateLock().wait();
              } catch (InterruptedException ie) {
              return false;
         if (failed)
         return false;
         else
         return true;
    * Inner Classes
    class StateListener implements ControllerListener {
         public void controllerUpdate(ControllerEvent ce) {
         // If there was an error during configure or
         // realize, the processor will be closed
         if (ce instanceof ControllerClosedEvent)
              setFailed();
         // All controller events, send a notification
         // to the waiting thread in waitForState method.
         if (ce instanceof ControllerEvent) {
              synchronized (getStateLock()) {
              getStateLock().notifyAll();
    * Sample Usage for VideoTransmitNew class
    public static void main(String [] args) {
         // We need three parameters to do the transmission
         // For example,
         // java VideoTransmitNew file:/C:/media/test.mov 129.130.131.132 42050
         System.err.println("Start transmission");
         //Create a video transmit object with the specified params.
    MediaLocator URL=new MediaLocator("file:///C:/media/test.mpg");
    //Am using 3 different threads.
         new VideoTransmitThread(URL,"CSELAB12PC10","9876").start();
         new VideoTransmitThread(URL," CSELAB12PC11","9870").start();
         new VideoTransmitThread(URL," CSELAB12PC12","9690").start();
         //close all transmission before quiting.

    Hm, that was my silver bullet. Other than doing an uninsall and then installing Presenter again, you may need to reach out to Adobe and see if they can identify what could be causing this.

  • MacBook Air or Pro for 2012 Student (heavy multitasker)?

    Hey Apple Community,
    Brief Background: I have been using the MacBook (December 2010), and it has been a boon - but it is time to move on. I waste anywhere between 1-3 hours just waiting for it to load, or else having to reboot it and open things again. Whatever I do, within an hour of use it just lags to the point where I end up doing my work on my iPhone or relocating to the school library where I can use a PC.
    As such, I want to buy a new MacBook. I will be writing two books, doing academic research, and soon starting my JD.
    I need a computer mainly for the following tasks:
    - Word processing et al (pages, word, powerpoint)
    - Internet (heavy multitabbing ... I mean very heavy)
    - Internet streaming films, shows, etc.
    - Music (Itunes)
    Perhaps most defining, I do all of these at the same time, utilizing Apple's 'Spaces' feature to the max - so the chosen mac would have to be very Multitask-Friendly (VERY!). I want something that will be able to effortlessly hold up all of these tasks at the same time. Harddrive space is less important (I am willing to put all of my music, movies and photos on an external harddrive if necessary). I'd like a computer that can do all of this very quickly, and would also be very portable (but I think the Pro is lightweight enough).
    I am leaning towards the MacBook Air.
    I would be grateful for any help at all.

    I think the MBair would meet your needs.  Here's a comparison with the MBpro.
    http://news.cnet.com/8301-13579_3-57458148-37/13-inch-macbook-air-vs-13-inch-mac book-pro-which-should-you-buy/?tag=postrtcol;posts

  • Okay, so I try to open an app, but for some reason, I can't close out of the app, multitask, or even shut of my iPod, so it won't lock, but I have the time set to two minutes but its been half an hour and it still didn't lock. Please tell me if fixable.

    I try to open up a texting app, and now, it won't lock, exit out (or crash suprisingly), multitask, or even power off. I also had auto lock set to two minutes and it has been about a full hour and it has never locked. If there is someone out there who has the same problem as me, and knows how to fix it, PLEASE TELL ME!!! I have a lot of texts that need to be answered... I also use the Assisstive touch and please tell me if that affects anything about these problems.

    Try:
    - iOS: Not responding or does not turn on
    - Also try DFU mode after try recovery mode
    How to put iPod touch / iPhone into DFU mode « Karthik's scribblings
    - If not successful and you can't fully turn the iOS device fully off, let the battery fully drain. After charging for an least an hour try the above again.
    - Try on another computer                            
    - If still not successful that usually indicates a hardware problem and an appointment at the Genius Bar of an Apple store is in order.
    Apple Retail Store - Genius Bar              

  • Pro*c multithreaded application has memory leak

    Hi there,
    I posted this message a week ago in OCI section, nobody answer me.
    I am really curious if my application has a bug or the pro*c has a bug.
    Anyone can compile the sample code and test it easily.
    I made multithreaded application which queries dynamic SQL, it works.
    But the memory leaks when i query the SQL statement.
    The more memory leaks, the more i query the SQL statement, even same SQL
    statement.
    I check it with top, shell command.
    My machine is SUN E450, Solaris 8. Oracle 9.2.0.1
    Compiler : gcc (GCC) 3.2.2
    I changed source code which is from
    $(ORACLE_HOME)/precomp/demo/proc/sample10.pc
    the sample10 doesn't need to be multithreaded. But i think it has to work
    correctly if i changed it to multithreaded application.
    the make file and source code will be placed below.
    I have to figure out the problem.
    Please help
    Thanks in advance,
    the make file is below
    HOME = /user/jkku
    ORA = $(ORACLE_HOME)
    CC = gcc
    PROC = proc
    LC_INCL = -I$(HOME)/work/dbmss/libs/include
    lc_incl = include=$(HOME)/work/dbmss/libs/include
    SYS_INCL =
    sys_incl =
    ORA_INCL = -I. \
    -I$(ORA)/precomp/public \
    -I$(ORA)/rdbms/public \
    -I$(ORA)/rdbms/demo \
    -I$(ORA)/rdbms/pbsql/public \
    -I$(ORA)/network/public \
    -DSLMXMX_ENABLE -DSLTS_ENABLE -D_SVID_GETTOD
    INCLUDES = $(LC_INCL) $(SYS_INCL) $(ORA_INCL)
    includes = $(lc_incl) $(sys_incl)
    LC_LIBS =
    SYS_LIBS = -lpthread -lsocket -lnsl -lrt
    ORA_LIBS = -L$(ORA)/lib/ -lclntsh
    LIBS = $(LC_LIBS) $(SYS_LIBS) $(ORA_LIBS)
    # Define C Compiler flags
    CFLAGS += -D_Solaris64_ -m64
    CFLAGS += -g -D_REENTRANT
    # Define pro*c Compiler flags
    PROCFLAGS += THREADS=YES
    PROCFLAGS += CPOOL=YES
    # Our object files
    PRECOMPS = sample10.c
    OBJS = sample10.o
    .SUFFIXES: .o .c .pc
    .c.o:
    $(CC) -c $(CFLAGS) $(INCLUDES) $*.c
    .pc.c:
    $(PROC) $(PROCFLAGS) $(includes) $*.pc $*.c
    all: sample10
    sample10: $(PRECOMPS) $(OBJS)
    $(CC) $(CFLAGS) -o sample10 $(OBJS) $(LIBS)
    clean:
    rm -rf *.o sample10 sample10.c
    the source code is below which i changed the oracle sample10.pc to
    multithreaded application.
    Sample Program 10: Dynamic SQL Method 4
    This program connects you to ORACLE using your username and
    password, then prompts you for a SQL statement. You can enter
    any legal SQL statement. Use regular SQL syntax, not embedded SQL.
    Your statement will be processed. If it is a query, the rows
    fetched are displayed.
    You can enter multi-line statements. The limit is 1023 characters.
    This sample program only processes up to MAX_ITEMS bind variables and
    MAX_ITEMS select-list items. MAX_ITEMS is #defined to be 40.
    #include <stdio.h>
    #include <string.h>
    #include <setjmp.h>
    #include <sqlda.h>
    #include <stdlib.h>
    #include <sqlcpr.h>
    /* Maximum number of select-list items or bind variables. */
    #define MAX_ITEMS 40
    /* Maximum lengths of the names of the
    select-list items or indicator variables. */
    #define MAX_VNAME_LEN 30
    #define MAX_INAME_LEN 30
    #ifndef NULL
    #define NULL 0
    #endif
    /* Prototypes */
    #if defined(__STDC__)
    void sql_error(void);
    int oracle_connect(void);
    int alloc_descriptors(int, int, int);
    int get_dyn_statement(void);
    void set_bind_variables(void);
    void process_select_list(void);
    void help(void);
    #else
    void sql_error(/*_ void _*/);
    int oracle_connect(/*_ void _*/);
    int alloc_descriptors(/*_ int, int, int _*/);
    int get_dyn_statement(/* void _*/);
    void set_bind_variables(/*_ void -*/);
    void process_select_list(/*_ void _*/);
    void help(/*_ void _*/);
    #endif
    char *dml_commands[] = {"SELECT", "select", "INSERT", "insert",
    "UPDATE", "update", "DELETE", "delete"};
    EXEC SQL INCLUDE sqlda;
    EXEC SQL INCLUDE sqlca;
    EXEC SQL BEGIN DECLARE SECTION;
    char dyn_statement[1024];
    EXEC SQL VAR dyn_statement IS STRING(1024);
    EXEC SQL END DECLARE SECTION;
    EXEC ORACLE OPTION (ORACA=YES);
    EXEC ORACLE OPTION (RELEASE_CURSOR=YES);
    SQLDA *bind_dp;
    SQLDA *select_dp;
    /* Define a buffer to hold longjmp state info. */
    jmp_buf jmp_continue;
    char *db_uid="dbmuser/dbmuser@dbmdb";
    sql_context ctx;
    int err_sql;
    enum{
    SQL_SUCC=0,
    SQL_ERR,
    SQL_NOTFOUND,
    SQL_UNIQUE,
    SQL_DISCONNECT,
    SQL_NOTNULL
    int main()
    int i;
    EXEC SQL ENABLE THREADS;
    EXEC SQL WHENEVER SQLERROR DO sql_error();
    EXEC SQL WHENEVER NOT FOUND DO sql_not_found();
    /* Connect to the database. */
    if (connect_database() < 0)
    exit(1);
    EXEC SQL CONTEXT USE :ctx;
    /* Process SQL statements. */
    for (;;)
    /* Allocate memory for the select and bind descriptors. */
    if (alloc_descriptors(MAX_ITEMS, MAX_VNAME_LEN, NAME_LEN) != 0)
    exit(1);
    (void) setjmp(jmp_continue);
    /* Get the statement. Break on "exit". */
    if (get_dyn_statement() != 0)
    break;
    EXEC SQL PREPARE S FROM :dyn_statement;
    EXEC SQL DECLARE C CURSOR FOR S;
    /* Set the bind variables for any placeholders in the
    SQL statement. */
    set_bind_variables();
    /* Open the cursor and execute the statement.
    * If the statement is not a query (SELECT), the
    * statement processing is completed after the
    * OPEN.
    EXEC SQL OPEN C USING DESCRIPTOR bind_dp;
    /* Call the function that processes the select-list.
    * If the statement is not a query, this function
    * just returns, doing nothing.
    process_select_list();
    /* Tell user how many rows processed. */
    for (i = 0; i < 8; i++)
    if (strncmp(dyn_statement, dml_commands, 6) == 0)
    printf("\n\n%d row%c processed.\n", sqlca.sqlerrd[2], sqlca.sqlerrd[2] == 1 ? '\0' : 's');
    break;
    /* Close the cursor. */
    EXEC SQL CLOSE C;
    /* When done, free the memory allocated for pointers in the bind and
    select descriptors. */
    for (i = 0; i < MAX_ITEMS; i++)
    if (bind_dp->V != (char *) 0)
    free(bind_dp->V);
    free(bind_dp->I); /* MAX_ITEMS were allocated. */
    if (select_dp->V != (char *) 0)
    free(select_dp->V);
    free(select_dp->I); /* MAX_ITEMS were allocated. */
    /* Free space used by the descriptors themselves. */
    SQLSQLDAFree(ctx, bind_dp);
    SQLSQLDAFree(ctx, select_dp);
    } /* end of for(;;) statement-processing loop */
    disconnect_database();
    EXEC SQL WHENEVER SQLERROR CONTINUE;
    EXEC SQL COMMIT WORK RELEASE;
    puts("\nHave a good day!\n");
    return;
    * Allocate the BIND and SELECT descriptors using sqlald().
    * Also allocate the pointers to indicator variables
    * in each descriptor. The pointers to the actual bind
    * variables and the select-list items are realloc'ed in
    * the set_bind_variables() or process_select_list()
    * routines. This routine allocates 1 byte for select_dp->V
    * and bind_dp->V, so the realloc will work correctly.
    alloc_descriptors(size, max_vname_len, max_iname_len)
    int size;
    int max_vname_len;
    int max_iname_len;
    int i;
    * The first sqlald parameter determines the maximum number of
    * array elements in each variable in the descriptor. In
    * other words, it determines the maximum number of bind
    * variables or select-list items in the SQL statement.
    * The second parameter determines the maximum length of
    * strings used to hold the names of select-list items
    * or placeholders. The maximum length of column
    * names in ORACLE is 30, but you can allocate more or less
    * as needed.
    * The third parameter determines the maximum length of
    * strings used to hold the names of any indicator
    * variables. To follow ORACLE standards, the maximum
    * length of these should be 30. But, you can allocate
    * more or less as needed.
    if ((bind_dp =
    SQLSQLDAAlloc(ctx, size, max_vname_len, max_iname_len)) ==
    (SQLDA *) 0)
    fprintf(stderr,
    "Cannot allocate memory for bind descriptor.");
    return -1; /* Have to exit in this case. */
    if ((select_dp =
    SQLSQLDAAlloc(ctx, size, max_vname_len, max_iname_len)) == (SQLDA *)
    0)
    fprintf(stderr,
    "Cannot allocate memory for select descriptor.");
    return -1;
    select_dp->N = MAX_ITEMS;
    /* Allocate the pointers to the indicator variables, and the
    actual data. */
    for (i = 0; i < MAX_ITEMS; i++) {
    bind_dp->I = (short *) malloc(sizeof (short));
    select_dp->I = (short *) malloc(sizeof(short));
    bind_dp->V = (char *) malloc(1);
    select_dp->V = (char *) malloc(1);
    return 0;
    int get_dyn_statement()
    char *cp, linebuf[256];
    int iter, plsql;
    for (plsql = 0, iter = 1; ;)
    if (iter == 1)
    printf("\nSQL> ");
    dyn_statement[0] = '\0';
    fgets(linebuf, sizeof linebuf, stdin);
    cp = strrchr(linebuf, '\n');
    if (cp && cp != linebuf)
    *cp = ' ';
    else if (cp == linebuf)
    continue;
    if ((strncmp(linebuf, "EXIT", 4) == 0) ||
    (strncmp(linebuf, "exit", 4) == 0))
    return -1;
    else if (linebuf[0] == '?' ||
    (strncmp(linebuf, "HELP", 4) == 0) ||
    (strncmp(linebuf, "help", 4) == 0))
    help();
    iter = 1;
    continue;
    if (strstr(linebuf, "BEGIN") ||
    (strstr(linebuf, "begin")))
    plsql = 1;
    strcat(dyn_statement, linebuf);
    if ((plsql && (cp = strrchr(dyn_statement, '/'))) ||
    (!plsql && (cp = strrchr(dyn_statement, ';'))))
    *cp = '\0';
    break;
    else
    iter++;
    printf("%3d ", iter);
    return 0;
    void set_bind_variables()
    int i, n;
    char bind_var[64];
    /* Describe any bind variables (input host variables) */
    EXEC SQL WHENEVER SQLERROR DO sql_error();
    bind_dp->N = MAX_ITEMS; /* Initialize count of array elements. */
    EXEC SQL DESCRIBE BIND VARIABLES FOR S INTO bind_dp;
    /* If F is negative, there were more bind variables
    than originally allocated by sqlald(). */
    if (bind_dp->F < 0)
    printf ("\nToo many bind variables (%d), maximum is %d\n.",
    -bind_dp->F, MAX_ITEMS);
    return;
    /* Set the maximum number of array elements in the
    descriptor to the number found. */
    bind_dp->N = bind_dp->F;
    /* Get the value of each bind variable as a
    * character string.
    * C contains the length of the bind variable
    * name used in the SQL statement.
    * S contains the actual name of the bind variable
    * used in the SQL statement.
    * L will contain the length of the data value
    * entered.
    * V will contain the address of the data value
    * entered.
    * T is always set to 1 because in this sample program
    * data values for all bind variables are entered
    * as character strings.
    * ORACLE converts to the table value from CHAR.
    * I will point to the indicator value, which is
    * set to -1 when the bind variable value is "null".
    for (i = 0; i < bind_dp->F; i++)
    printf ("\nEnter value for bind variable %.*s: ",
    (int)bind_dp->C, bind_dp->S);
    fgets(bind_var, sizeof bind_var, stdin);
    /* Get length and remove the new line character. */
    n = strlen(bind_var) - 1;
    /* Set it in the descriptor. */
    bind_dp->L = n;
    /* (re-)allocate the buffer for the value.
    sqlald() reserves a pointer location for
    V but does not allocate the full space for
    the pointer. */
    bind_dp->V = (char *) realloc(bind_dp->V, (bind_dp->L + 1));
    /* And copy it in. */
    strncpy(bind_dp->V, bind_var, n);
    /* Set the indicator variable's value. */
    if ((strncmp(bind_dp->V, "NULL", 4) == 0) ||
    (strncmp(bind_dp->V, "null", 4) == 0))
    *bind_dp->I = -1;
    else
    *bind_dp->I = 0;
    /* Set the bind datatype to 1 for CHAR. */
    bind_dp->T = 1;
    return;
    void process_select_list()
    int i, null_ok, precision, scale;
    if ((strncmp(dyn_statement, "SELECT", 6) != 0) &&
    (strncmp(dyn_statement, "select", 6) != 0))
    select_dp->F = 0;
    return;
    /* If the SQL statement is a SELECT, describe the
    select-list items. The DESCRIBE function returns
    their names, datatypes, lengths (including precision
    and scale), and NULL/NOT NULL statuses. */
    select_dp->N = MAX_ITEMS;
    EXEC SQL DESCRIBE SELECT LIST FOR S INTO select_dp;
    /* If F is negative, there were more select-list
    items than originally allocated by sqlald(). */
    if (select_dp->F < 0)
    printf ("\nToo many select-list items (%d), maximum is %d\n",
    -(select_dp->F), MAX_ITEMS);
    return;
    /* Set the maximum number of array elements in the
    descriptor to the number found. */
    select_dp->N = select_dp->F;
    /* Allocate storage for each select-list item.
    sqlprc() is used to extract precision and scale
    from the length (select_dp->L).
    sqlnul() is used to reset the high-order bit of
    the datatype and to check whether the column
    is NOT NULL.
    CHAR datatypes have length, but zero precision and
    scale. The length is defined at CREATE time.
    NUMBER datatypes have precision and scale only if
    defined at CREATE time. If the column
    definition was just NUMBER, the precision
    and scale are zero, and you must allocate
    the required maximum length.
    DATE datatypes return a length of 7 if the default
    format is used. This should be increased to
    9 to store the actual date character string.
    If you use the TO_CHAR function, the maximum
    length could be 75, but will probably be less
    (you can see the effects of this in SQL*Plus).
    ROWID datatype always returns a fixed length of 18 if
    coerced to CHAR.
    LONG and
    LONG RAW datatypes return a length of 0 (zero),
    so you need to set a maximum. In this example,
    it is 240 characters.
    printf ("\n");
    for (i = 0; i < select_dp->F; i++)
    char title[MAX_VNAME_LEN];
    /* Turn off high-order bit of datatype (in this example,
    it does not matter if the column is NOT NULL). */
    sqlnul ((unsigned short *)&(select_dp->T), (unsigned short
    *)&(select_dp->T), &null_ok);
    switch (select_dp->T)
    case 1 : /* CHAR datatype: no change in length
    needed, except possibly for TO_CHAR
    conversions (not handled here). */
    break;
    case 2 : /* NUMBER datatype: use sqlprc() to
    extract precision and scale. */
    sqlprc ((unsigned int *)&(select_dp->L), &precision,
    &scale);
    /* Allow for maximum size of NUMBER. */
    if (precision == 0) precision = 40;
    /* Also allow for decimal point and
    possible sign. */
    /* convert NUMBER datatype to FLOAT if scale > 0,
    INT otherwise. */
    if (scale > 0)
    select_dp->L = sizeof(float);
    else
    select_dp->L = sizeof(int);
    break;
    case 8 : /* LONG datatype */
    select_dp->L = 240;
    break;
    case 11 : /* ROWID datatype */
    case 104 : /* Universal ROWID datatype */
    select_dp->L = 18;
    break;
    case 12 : /* DATE datatype */
    select_dp->L = 9;
    break;
    case 23 : /* RAW datatype */
    break;
    case 24 : /* LONG RAW datatype */
    select_dp->L = 240;
    break;
    /* Allocate space for the select-list data values.
    sqlald() reserves a pointer location for
    V but does not allocate the full space for
    the pointer. */
    if (select_dp->T != 2)
    select_dp->V = (char *) realloc(select_dp->V,
    select_dp->L + 1);
    else
    select_dp->V = (char *) realloc(select_dp->V,
    select_dp->L);
    /* Print column headings, right-justifying number
    column headings. */
    /* Copy to temporary buffer in case name is null-terminated */
    memset(title, ' ', MAX_VNAME_LEN);
    strncpy(title, select_dp->S, select_dp->C);
    if (select_dp->T == 2)
    if (scale > 0)
    printf ("%.*s ", select_dp->L+3, title);
    else
    printf ("%.*s ", select_dp->L, title);
    else
    printf("%-.*s ", select_dp->L, title);
    /* Coerce ALL datatypes except for LONG RAW and NUMBER to
    character. */
    if (select_dp->T != 24 && select_dp->T != 2)
    select_dp->T = 1;
    /* Coerce the datatypes of NUMBERs to float or int depending on
    the scale. */
    if (select_dp->T == 2)
    if (scale > 0)
    select_dp->T = 4; /* float */
    else
    select_dp->T = 3; /* int */
    printf ("\n\n");
    /* FETCH each row selected and print the column values. */
    EXEC SQL WHENEVER NOT FOUND GOTO end_select_loop;
    for (;;)
    EXEC SQL FETCH C USING DESCRIPTOR select_dp;
    /* Since each variable returned has been coerced to a
    character string, int, or float very little processing
    is required here. This routine just prints out the
    values on the terminal. */
    for (i = 0; i < select_dp->F; i++)
    if (*select_dp->I < 0)
    if (select_dp->T == 4)
    printf ("%-*c ",(int)select_dp->L+3, ' ');
    else
    printf ("%-*c ",(int)select_dp->L, ' ');
    else
    if (select_dp->T == 3) /* int datatype */
    printf ("%*d ", (int)select_dp->L,
    *(int *)select_dp->V);
    else if (select_dp->T == 4) /* float datatype */
    printf ("%*.2f ", (int)select_dp->L,
    *(float *)select_dp->V);
    else /* character string */
    printf ("%-*.*s ", (int)select_dp->L,
    (int)select_dp->L, select_dp->V);
    printf ("\n");
    end_select_loop:
    return;
    void help()
    puts("\n\nEnter a SQL statement or a PL/SQL block at the SQL> prompt.");
    puts("Statements can be continued over several lines, except");
    puts("within string literals.");
    puts("Terminate a SQL statement with a semicolon.");
    puts("Terminate a PL/SQL block (which can contain embedded
    semicolons)");
    puts("with a slash (/).");
    puts("Typing \"exit\" (no semicolon needed) exits the program.");
    puts("You typed \"?\" or \"help\" to get this message.\n\n");
    int connect_database()
    err_sql = SQL_SUCC;
    EXEC SQL WHENEVER SQLERROR DO sql_error();
    EXEC SQL WHENEVER NOT FOUND DO sql_not_found();
    EXEC SQL CONTEXT ALLOCATE :ctx;
    EXEC SQL CONTEXT USE :ctx;
    EXEC SQL CONNECT :db_uid;
    if(err_sql != SQL_SUCC){
    printf("err => connect database(ctx:%ld, uid:%s) failed!\n", ctx, db_uid);
    return -1;
    return 1;
    int disconnect_database()
    err_sql = SQL_SUCC;
    EXEC SQL WHENEVER SQLERROR DO sql_error();
    EXEC SQL WHENEVER NOT FOUND DO sql_not_found();
    EXEC SQL CONTEXT USE :ctx;
    EXEC SQL COMMIT WORK RELEASE;
    EXEC SQL CONTEXT FREE:ctx;
    return 1;
    void sql_error()
    printf("err => %.*s", sqlca.sqlerrm.sqlerrml, sqlca.sqlerrm.sqlerrmc);
    printf("in \"%.*s...\'\n", oraca.orastxt.orastxtl, oraca.orastxt.orastxtc);
    printf("on line %d of %.*s.\n\n", oraca.oraslnr, oraca.orasfnm.orasfnml,
    oraca.orasfnm.orasfnmc);
    switch(sqlca.sqlcode) {
    case -1: /* unique constraint violated */
    err_sql = SQL_UNIQUE;
    break;
    case -1012: /* not logged on */
    case -1089:
    case -3133:
    case -1041:
    case -3114:
    case -3113:
    /* �6�Ŭ�� shutdown�ǰų� �α��� ���°� �ƴҶ� ��b�� �õ� */
    /* immediate shutdown in progress - no operations are permitted */
    /* end-of-file on communication channel */
    /* internal error. hostdef extension doesn't exist */
    err_sql = SQL_DISCONNECT;
    break;
    case -1400:
    err_sql = SQL_NOTNULL;
    break;
    default:
    err_sql = SQL_ERR;
    break;
    EXEC SQL CONTEXT USE :ctx;
    EXEC SQL WHENEVER SQLERROR CONTINUE;
    EXEC SQL ROLLBACK WORK;
    void sql_not_found()
    err_sql = SQL_NOTFOUND;

    Hi Jane,
    What version of Berkeley DB XML are you using?
    What is your operating system and your hardware platform?
    For how long have been the application running?
    What is your current container size?
    What's set for EnvironmentConfig.setThreaded?
    Do you know if containers have previously not been closed correctly?
    Can you please post the entire error output?
    What's the JDK version, 1.4 or 1.5?
    Thanks,
    Bogdan

  • What is the point of the multitasking bar?

    So, I get that for Pandora, Skype, etc. that multitasking is great. I just opened up my multitasking bar though, and found the following "open" items: Messages, Mail, Calendar, Camera, Settings, Map, Weather, Calculator, YouTube, Compass, IMDb, Facebook, Twitter, Shazam, and four games.
    Why in the world would I care about saving my session for any of these? Especially when they all go back to the same screen as I was at last time anyway. Now I have to go through and "close" all of them?
    I feel like I'm missing something. Can anyone shed some light for me?

    The purpose of the multitasking bar is to keep your apps running in the background with seven key features. Amongst those features are:
    * Fast App Switching - Pauses games and apps until you swap back or press the icon in your home screen to resume it.
    * Background Running and Location Services - GPS, music and social apps still run and announce directions for you while you are navigating other screens. But utilize FAS to lower power costs.
    * File Transfers and Task Completions - You're uploading a 50KB photo to your Facebook page and want to go elsewhere while it's going on. It'll freeze the app in the meantime but continue the file transfer until it's done then lock it down.
    You don't have to re-open multitasker to reactivate the app. You can open the file from the home screen and it pops back up.
    The ideal for the multitasker also if you wish to increase battery life and performance is you can close them at will including reactivate the apps there. However if you close them, you have to start from the beginning of the application. Making it take longer to resume your sessions.

  • How to configure ENV and DB for multithreaded application?

    Hi,
    From document, I know DB_THREAD must be checked for both ENV and DB, but , I don't know which one is best choice for multithreaded application while facing DB_INIT_LOCK and DB_INIT_CDB. In my application, there maybe multi readers and writers at the same time, should I use DB_INIT_LOCK instead of DB_INIT_CDB? what other flags should I use?
    DB_INIT_CDB provides multiple reader/single writer access while DB_INIT_LOCK should be used when multiple processes or threads are going to be reading and writing a Berkeley DB database.
    Thanks for your seggestions and answers.

    Thanks for the explanation,
    The Berkeley DB Concurrent Data Store product
    allows for multiple reader/single writer access
    to a database. This means that at any point in time,
    there may be either multiple readers accessing a
    database or a single writer updating the database.
    Berkeley DB Concurrent Data Store is intended for
    applications that need support for concurrent updates
    to a database that is largely used for reading.
    If you are looking to support multiple readers and
    multiple writers then take a look at the Transactional
    Data Store product
    (http://download.oracle.com/docs/cd/E17076_02/html/programmer_reference/transapp.html)
    In this case the Environment is typically opened with:
    DB_INIT_MPOOL, DB_INIT_LOCK, DB_INIT_LOG, and DB_INIT_TXN.
    Let me know if I missed any of your question.
    Thanks,
    Sandra

  • Use multi-touch to close more than one app at a time in the multitask bar!!

    Is this a new feature? I was always annoyed that I had to tap each red x one at a time to close an app on the multitasking bar, so I decided to try and tap several at a time and voilà! It works! I've been able to tap two at a time. Let me know if anyone can do more! I wish they would add a "close all" button, but in the meantime this helps a lot!!!

    You only have two fingers? Yes, you can close 4 at a time.

  • Frequent LowMemory crash when starting multitasking by double-click Home button

    After upgrading iOS 7, my iPhone 5 crashes when double-clicking home button for multitasking.
    The crush shows white apple logo and reboots my iPhone.
    It occurs about 2-3 times a day.
    Every time crash occurs, Diagnostic & Usage Data would add a LowMemory log, which is exactly the time iPhone crashes.
    Therefore I guess it's because of running out memory.
    I've tried Reset My Phone, Reduce Motion, Disable Background App Fresh..., but none of it worked.
    My iPhone begins to crash 3 days after resetting.
    Does anybody know how to solve it?

    I think you mean crash.
    Also, I am going to assume you've tried restarting and reseting. What you can do is back up the important information in your phone (using either iTunes or iCloud) and restore the device as new. Then, you can restore from your backup. This will remove any and all software bugs.

  • Multithreading - writing to file

    How can I get to write the Thread name, date and time to a file with the same thread name?
    What would I need to do to write the same information 1000 times to the file? Thank you.
    import java.lang.Thread;
    import java.lang.InterruptedException;
    public class RiveraThreadsMain {
        public static void main(String[] args) {
          System.out.println("Creating threads");
          Thread riverathread0 = new Thread (new RiveraThreads ("riverathread0"));
          Thread riverathread1 = new Thread (new RiveraThreads ("riverathread1"));
          Thread riverathread2 = new Thread (new RiveraThreads ("riverathread2"));
          System.out.println("Threads created, starting tasks.");
          riverathread0.start(); // invokes thread1's run method
          riverathread1.start(); // invokes thread2's run method
          riverathread2.start(); // invokes thread3's run method
          try
           Thread.currentThread() .sleep (10000);
          catch (InterruptedException e)
            e.getStackTrace();
             System.out.printf (
             "terminated prematurely due to interruption");
          System.out.println("Tasks started, main thread ends. \n");   
        } // end main
    import java.io.File;
    import java.io.IOException;
    import java.util.NoSuchElementException;
    import java.io.FileNotFoundException;
    import java.util.Formatter;
    import java.util.NoSuchElementException;
    import java.util.Calendar;
    import java.util.Scanner;
    public class RiveraThreads implements Runnable {
    Thread launcher;
    private String taskName;
    private Scanner input;
    private Formatter output;
    // empty constructor
    public RiveraThreads (){
      public RiveraThreads (String threadName)
        launcher = new Thread ( this, threadName );
        System.out.println ( launcher.getName());
        launcher.start();
       // taskName = name; // set task name
      public void run ()
        //System.out.println(Thread.currentThread().getName());
        try
          Calendar dateTime = Calendar.getInstance();
        //  output = new Formatter (new File (launcher.getName() ));
          input = new Scanner( new File( launcher.getName() ) ); 
          output = new Formatter (new File ( launcher.getName() ));
          System.out.printf( launcher.getName() + "%tc\n", dateTime );
        }// end try
        catch ( NoSuchElementException exception)
            exception.getStackTrace();
            System.out.printf ( "%s %s \n ", taskName,
             "terminated prematurely due to interruption");
        }// end catch
        catch ( FileNotFoundException filenotfound )
            System.out.printf (" %s %s \n ", filenotfound,
              "File not found");
        catch (IOException ioexception)
          System.err.printf(
            "Unable to read file");
        // close file and terminate application
       public void closeFile()
             input.close();
          }// close file
              output.close();
       } // end method closeFile
    }

    FRiveraJr wrote:
    Hi jverd
    What are you having trouble with?
    I know how to use the BufferedReader and BufferedWriter for opening, reading and writing to file. But the trouble consists in a lot of code to write and how will I call the appropriate file name since it is supposed to be
    the same name as the thread into all of this? I still don't know what problem you're having.
    You know how to provide a file name, right?
    Do you know how to get a thread name?
    If both are "yes", then I don't see what's left that you'd be having problems with. You need to be specific. Nobody here can read your mind, since it's the holidays.
    Writing to a file?
    Yes, I'm getting the correct results to the console with the thread name and the calendar option with the date and time and this is the data that needs to be written to a file. Isn't there a more simple way?A simpler way than your current code? How can anybody answer that without seeing your code?
    What would I need to do to write the same information 1000 times to the file?
    Because that is part of the requirements. Is not that I am insane :0).... This is just part of developing my skills since I'm new to all this. So, do you still have a question about this part? You do know how to loop, right? If not, you shouldn't be getting anywhere near I/O or multithreading.

Maybe you are looking for